链队
(相当于开创一个结构体,结构体里跟随一个链表)
结构体声明和宏
typedef int data_t;
//构造链表节点类型
typedef struct node{
data_t data;
struct node *next;//指针域
}linklist;
//构造链式队列类型 //相当与构建头节点、尾节点
typedef struct{
linklist *front;//保存队头节点的前一个节点的地址
linklist *rear;//保存队尾节点的地址
}lqueue;
注意的两个结构体里的类型和相互的关系
1.创建空链队(类似于创建头节点)
//创建空链式队列
lqueue *createLqueue()
{
lqueue *lq = (lqueue *)malloc(sizeof(lqueue));//给链式队列开空间
if(NULL == lq) return NULL;
lq->front = (linklist *)malloc(sizeof(linklist));//给链表头节点开空间
if(lq->front == NULL) return NULL;
lq->rear = lq->front; //空
lq->front->data = -1;
lq->front->next = NULL;
return lq;
}
注意创建的节点的关系,以及初始化为空,故front=rear
2.判空
//判空
int lqueue_is_empty(lqueue *lq)
{
if(NULL == lq)
return -1;
else
return ((lq->front == lq->rear)?1:0);
}
3.求节点个数
int getLengthLqueue(lqueue *lq)
{
if(lq == NULL)
return -1;
int num = 0;
linklist *p = lq->front->next;
while(p != NULL)
{
num++;
p = p->next;
}
return num;
}
4.入队
//入队,在队尾入队
int enLqueue(lqueue *lq,data_t data)
{
if(NULL == lq) return -1;
linklist *new = (linklist *)malloc(sizeof(linklist));//准备新节点
if(NULL == new) return -1;
new->data = data;
new->next = NULL;
//rear本来就记录着尾节点,不用遍历到尾部
//将new节点插入到队尾
lq->rear->next = new;
lq->rear = new;//new节点为队尾节点,更新尾部
return 0;
}
注意尾部的更新
5.出队(两种方式)
//出队
//head保持不变,删除第一个节点,需要判断是否为空
data_t deLqueue(lqueue *lq)
{
if(lq == NULL) return -1;
if(lqueue_is_empty(lq)) return -1;
linklist *q = lq->front->next; //q指针保存队头节点(第一个节点)的地址 、head保持不变
data_t data = q->data; //data变量保存队头元素的data值
lq->front->next = q->next; //删除队头节点(第一个节点)
if(lq->front->next == NULL) //判断队列是否为空
lq->rear = lq->front; //front和rear指针指向头节点
free(q);
q = NULL;
return data;
}
//head向后移动,不断删除头节点,再重新赋头节点,不用判断,head(lq->front)和lq->rear相遇时就为空了
data_t deLqueue(lqueue *lq)
{
if(lq == NULL) return -1;
if(lqueue_is_empty(lq)) return -1;
data_t tmp=lq->front->next->data; //运用的是删除head头节点的方式
linklist *q=lq->front; // 将lq->front给下一个节点,该节点被当作头节点数据区无效了,效果相同
lq->front=lq->front->next;
free(q); //不用判断是否为空,删除头节点,front所在就是头节点,为空时回合rear相遇
}
注意判断最后一个节点删除后,应该front=rear
6.show
//打印队列中各个节点的daya值
void printLqueue(lqueue *lq)
{
if(NULL == lq) return;
if(lqueue_is_empty(lq)) return;
linklist *p = lq->front->next;//p变量保存的是队头节点的地址
while(p != NULL)//遍历队列
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return;
}
重新让一个节点p指向头,让其用来遍历,就不用一直释放遍历
算法思路
创建倒数第二行代码:lq->front->next=NULL
数据结构参考网站:
https://visualgo.net/en/list