算法与数据机构入门经典(链表实现队列)(完美解决free函数出错问题-内存管理)

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,首先把指针解引用是吧。->相当于把解引用这一步集成了。。。

    ->和  .  的差异:其实就是个解引用的差异而已。(-> 和 . 的区别是针对他们前面是指针还是实体)

    彩蛋:(关于坑的问题你还记得多少??好好问问你自己)


      谢谢战友算法与数据结构昌俊对我的大力指导。我如果有说错的,希望大家可以帮我留言指正,如果对您有帮助,请在您内容前留下我博客号就可以转载分享。

 


猜你喜欢

转载自blog.csdn.net/qq_37791134/article/details/80883850