1.队列是一种线性存储结构,(链表是非连续、非顺序、的链式存储结构)(栈(Stack)是一种线性存储结构),和栈一样,是线性存储结构,具有以下特点:
(1)队列中的数据元素遵守先进先出(First In First Out)的原则。
(2)限定只能在队列头部与尾部进行插入和删除操作。
(3)标准的队列包括以下 5个操作:
头部
尾部
实现队列,链表和数组两种方法。
2.链表实现队列
3.队列的基本操作,入队操作
将某元素添加至队列:
1。创建一个新节点new_node.
2.将tail_node指向的节点的值赋值为待添加的值
2.将tail_node的next指向新节点
3.将head_node指向new_node。
5.修改队列的元素个数
步骤示意图如下:
4.队列的基本操作,出对操作
将队头元素弹出队列:
步骤:1判断队列是否为空,为空直接返回;
2top_node备份节点
3移动head_node指针到head_node->next指向的节点
4修改队列元素个数
5释放弹出节点 需要用#include<malloc.h>
5.队列的其他基本操作
返回队列底操作也 = 返回队列头部元素。
求队列大小 = 求队列存储元素个数。
判断队列是否为空。
6.队列的基本操作,代码测试
#include <stdio.h>
#include<malloc.h>
//单链表数据结构
typedef struct ListNode ListNode;
struct ListNode {
int data;
ListNode *next;
};
typedef struct Queue Queue;
struct Queue {
ListNode node; //预留一个头节点
ListNode *head_node; //队列尾部指针
ListNode *tail_node; //队列头部指针
int size;//队列中元素个数
};
//队列的初始化
void queue_init(Queue *queue) {
queue->node.data = 0;
queue->node.next = NULL;
queue->tail_node = &queue->node;
queue->head_node = &queue->node;
queue->size = 0;
}
//入队操作
void queue_push(Queue *queue, int data) {
ListNode *new_node = (ListNode *)malloc(sizeof(ListNode));
new_node->data = 0; //创建新节点new_node
new_node->next = NULL;
queue->tail_node->data = data;//将data赋值为尾节点的值
queue->tail_node->next = new_node;//将尾节点的next指向新节点(从左往右读)
queue->tail_node = new_node;//将尾节点指向new_node;
queue->size += 1;
}
//出队操作
void queue_pop(Queue *queue) {
if (queue->tail_node == queue->head_node) { //1判断队列是否为空,为空直接返回
return;
}
ListNode *top_node = queue->head_node;//2top_node备份节点
queue->head_node = queue->head_node->next; //3移动head_node指针到head_node->next指向的节点
queue->size -= 1;//4修改队列元素个数
free(top_node);//5释放弹出节点 需要用#include<malloc.h>
//queue->head_node = NULL;
//top_node = NULL;
}
//返回队列头部元素
int queue_front(Queue * queue) {
return queue->head_node->data;
}
//判断是否为空
int queue_is_empty(Queue *queue) {
return queue->tail_node == queue->head_node;
}
//求队列存储元素个数
int queue_size(Queue *queue) {
return queue->size;
}
void queue_print(Queue *queue) {
printf("Queue:\n");
ListNode *p = queue->head_node;
while (p) {
printf("[%d]\n", p->data);
p = p->next;
}
}
int main() {
Queue queue;//定义一个队列
queue_init(&queue);//初始化队列
queue_print(&queue);
queue_push(&queue, 4);
queue_push(&queue, 6);
queue_push(&queue, 5);
queue_print(&queue);
printf("Queue front value is %d\n", queue_front(&queue));
printf("Queue size is %d\n", queue_size(&queue));
printf("Queue empty is %d\n", queue_is_empty(&queue));
printf("\n");
queue_pop(&queue);
queue_pop(&queue);
queue_print(&queue);
printf("Queue front value is %d\n", queue_front(&queue));
printf("Queue size is %d\n", queue_size(&queue));
printf("Queue empty is %d\n", queue_is_empty(&queue));
printf("\n");
queue_pop(&queue);
queue_print(&queue);
printf("Queue size id %d\n", queue_size(&queue));
printf("Queue empty is %d\n", queue_is_empty(&queue));
return 0;
}
受到伤害 ,说断言失败!omg ,我第一次出现这种bug,所以说还是得学会调试代码,否则自己遇到问题总是不会解决,这个还得人教呀。。。抱大腿。。。
还是free函数的问题。
但怎么解决呢?
按照http://c.biancheng.net/cpp/html/135.html对free函数的介绍,加了top_node =NULL;也没有用、
我感觉我只要停止别人多我的帮助,我就失去了前进,说白了就是不会解决问题。大海里找解决办法,一个一个尝试,难道就没有总结性的操作吗?
有人说在release下可以,然后不是的。。。
C语言是很坑的,关于内存管理的问题,简直让人心烦,所以很多人选择用C++和JAVA学习数据结构。
但是C++有对象也不是一个省油灯。
最终解决方案:
queue中,是有预留了一个头结点的,而这个头结点是非动态分配的。所以这个头结点free会失败。要改的话,就吧这个头节点也改成动态分配的就可以了。
代码改写如上哦 。
C语言中&是什么意思?
两种功能, 第一种.取变量地址. int a; int *p; p=&a; 第二种.位与运算 0000010 & 1111111 =0000010
现在定义为结构体指针,指向结构体的指针,所以是用-> 而不是用. 有的时候会弄错这两个符号的使用 ???
得知->是指针专用,.号是实体专用的。你想呀,如果要用指针去访问,正常来说是不是应该这样(*p).xxx,首先把指针解引用是吧。->相当于把解引用这一步集成了。。。
->和 . 的差异:其实就是个解引用的差异而已。(-> 和 . 的区别是针对他们前面是指针还是实体)
彩蛋:(关于坑的问题你还记得多少??好好问问你自己)
谢谢战友算法与数据结构昌俊对我的大力指导。我如果有说错的,希望大家可以帮我留言指正,如果对您有帮助,请在您内容前留下我博客号就可以转载分享。