Linux学习(十一):数据结构之栈和队列
2017-09-12 21:01
381 查看
1、栈
栈的存储规则是先进后出。学习嵌入式的同学都知道中断时的现场保护,当有中断嵌套时采用的也是先进后出的原则,和栈是一样的。看过上一节Linux学习(十):数据结构--表的同学对数组表和链表已经有了了解。对于栈来讲,用上一节讲到的知识,做一些简单修改就可以实现栈的功能。这里只做简单介绍。
对于数组形式的栈,只要记住将删除函数的返回值改为data_t类型,函数中返回要用的数。其余都是一样的。
data_t sqstack_pop(sqstack_t *stack) { if(sqstack_is_empty(stack)) { // puts("empty"); return -1; } data_t value = 0; value = stack->a[stack->top]; stack->top--; return value; }对于链表,我们讲到了头插入,尾插入,头删除,尾删除法。我们一般用头插入和头删除结合的方法。因为尾插入和尾删除都需要进行找寻最后节点的过程,相对而言麻烦了些。同样头删除时将数据返回。
data_t linkstack_pop(linknode_t *stack) { if(linkstack_is_empty(stack)) { // puts("empty"); return -1; } linknode_t *temp = stack->next; data_t value = temp->data; stack->next = temp->next; free(temp); temp = NULL; return value; }
2、队列
队列与栈正好相反,采用的是先进先出的原则。我们仍使用上一节的知识为基础,来实现数组队列和链式队列。2.1 数组队列
对于数组队列来讲,由于是先进先出的原则,最先出的前面的数据,而我们之前用的last只能指示最后的数据,会造成空间的浪费
例如,有4个空间的队列,填满后为1 3 5 7,此时我们压出一个数据,1被压出,但此时我们的last仍指向最后,整个数组队列仍然指示为满状态。为了解决这种情况,我们设置两个标志位。一个队头的下标front,另一个是队尾的下一个下标,队列为空时,两者相等,但同时,空间满时,两者也相等,为了以示区别,我们留出一个空间,当rear比front大1时我们认为此时为满状态。
2.1 创建队列
typedef int data_t; typedef struct queue{ data_t a ; int front; int rear; }sqqueue_t; sqqueue_t *sqqueue_create() { sqqueue_t * queue = (sqqueue_t *)malloc(sizeof(sqqueue_t)); queue->front = 0; queue->rear = 0; return queue; }
2.1 压入数据
int sqqueue_is_full(sqqueue_t *queue) { return (queue->rear + 1) % N == queue->front ? 1 : 0; }这里要注意rear+1后要注意取余操作,这样数组队列才能循环利用
int sqqueue_input(sqqueue_t *queue, data_t value) { if(sqqueue_is_full(queue)) { printf("full\n"); return -1; } queue->a[ queue->rear ] = value; queue->rear = (queue->rear+1) % N; return 0; }
2.2 取数据
int sqqueue_is_empty(sqqueue_t *queue) { return queue->rear == queue->front ? 1 : 0; }
data_t sqqueue_output(sqqueue_t *queue) { if(sqqueue_is_empty(queue)) { printf("empty\n"); return -1; } data_t value = queue->a[ queue->front ]; queue->front = (queue->front + 1) % N; return value; }同样要注意front取值后的取余操作。
3、链表实现队列
链表实现队列时,除了定义一个节点变量,再定义一个队列结构体变量,包含一个头节点指针和一个尾节点指针。typedef int data_t; typedef struct node { data_t data; struct node * next; }link_node; typedef struct queue { link_node *head; //指向队列的头节点 link_node *tail; //指向队列的最后一个节点 }queue_t;
3.1 队列创建
队列创建时令头节点指针和尾节点指针相等,这也就是队列为空的情况queue_t *link_queue_creat() { queue_t *queue = (queue_t *)malloc(sizeof(queue_t)); queue->head = (link_node *)malloc(sizeof(link_node)); queue->tail = (link_node *)malloc(sizeof(link_node)); queue->head = queue->tail; queue->tail->next = NULL; return queue; }
3.2 队列添加
队列添加采用尾添加的方式,从尾部入队,移动tail指针即可int link_queue_add(queue_t *queue,data_t value) { link_node *node = (link_node *)malloc(sizeof(link_node)); node->data = value; node->next = NULL; queue->tail->next = node; queue->tail = node; return 0; }
3.3 队列弹出数据
队列出数据是采用头删除的方法,也就是从头节点弹出数据。int is_empty(queue_t *queue) { return queue->head ==queue->tail?1:0; } data_t link_queue_output(queue_t *queue) { link_node *temp; data_t temp_data; if(is_empty(queue)) { return -1; } temp = queue->head->next; queue->head->next = temp->next; if(temp->next == NULL) { queue->tail = queue->head; } temp_data = temp->data; free(temp); temp = NULL; return temp_data; }
要注意15-18行的代码,当弹出最后一个数据并释放其地址空间时,tail指针仍然指向原来的地址,但那块地址空间已经被释放了,此时必须让tail指针指向队列的头节点。从另一个方面思考,返回最后一个数据时,队列已经为空,为空的条件是什么?头节点和尾节点指向同一块地址,自然两者应相等。
相关文章推荐
- 数据结构学习笔记-队列的链式存储(C语言实现)
- Linux学习之十一、环境变量的功能
- 学习算法和数据结构:栈和队列
- 实验楼Linux学习笔记(十一)之数据流重定向
- Linux内核等待队列wait_queue学习
- 数据结构学习的简单问题(四):用队列自己实现String类
- linux C++ queue 队列 学习积累
- linux内核学习——工作队列
- linux之等待队列--阻塞型驱动学习---学习笔记
- Linux netfilter 学习笔记 之十一 ip层netfilter的NAT模块初始化以及NAT原理
- Linux netfilter 学习笔记 之七 ip层netfilter的连接跟踪模块的概念及相关的数据结构分析
- linux学习二内存管理重要的数据结构
- 数据结构学习笔记3-队列
- 数据结构学习笔记 --- 栈、队列 (习题)
- 数据结构学习之队列
- 数据结构学习三:队列
- 发送队列的默认队列策略 (linux网络子系统学习 第十一节 )
- (C语言)队列的链式实现(数据结构十一)
- Linux 2.4.30 内核文件系统学习(多图) 1 : 关键数据结构
- 【Linux学习笔记十一】linux文件和目录属性管理