您的位置:首页 > 理论基础 > 数据结构算法

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指针指向队列的头节点。从另一个方面思考,返回最后一个数据时,队列已经为空,为空的条件是什么?头节点和尾节点指向同一块地址,自然两者应相等。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: