前言
在上次的文章中,我們實現了隊列的順序存儲,也就是循環隊列,既然有順序存儲,那就有鏈式存儲。鏈式有個問題,究竟是需要頭結點呢,還是不需要頭結點呢,其實都可以,在鏈棧中我們使用的是沒有頭結點,那麼在鏈隊中我們就用有頭結點的結構
1.循環隊列和鏈隊列的區別
在空間上,鏈隊列比較靈活。在可以確定隊列長度最大值的情況下,建議使用循環隊列,如果你無法預估隊列的長度時,則用鏈隊列
2.鏈隊的定義
鏈隊也和鏈棧一樣,需要兩個結構體來定義,但是在實現過程中發現統計隊列長度時不好統計,那麼我們就和鏈棧一樣,給直接他設置一個計數器。來統計隊列的長度。統計時直接返回計數器的值。
//定義結點
typedef struct QNode
{
QElemType data;
struct QNode* next;
}QNode,*QueuePtr;
//定義鏈隊列
typedef struct
{
QueuePtr front,rear;//隊頭指針和隊尾指針
int count;//計數器
}LinkQueue;
3.有無頭結點之分
有無頭結點之分,其實是體現在初始化上
1.在鏈棧中,我們沒有使用頭結點,從代碼中可以看到,沒有頭結點時棧頂指針直接指向空,其初始化:
//沒有頭結點的鏈棧初始化
Status InitStack(LinkStack *s)
{
s->top = NULL;
s->count = 0;
return OK;
}
2.在這片鏈隊的初始化中,有頭結點,利用第一個結構體創造出頭結點,讓隊頭和隊尾指針都指向這個創造的頭結點,其初始化:
//有頭結點鏈隊的初始化
Status InitQueue(LinkQueue *Q)
{
QueuePtr head = (QueuePtr)malloc(sizeof(QNode));
head->next = NULL;
Q->front = head;
Q->rear = head;
Q->count = 0;
return OK;
}
4.內容佈局
本篇文章所涉及的主要操作有:
1.入隊:
Q->rear->next = s;
Q->rear = s;
Q->count++;
2.出隊:
QueuePtr p;
QElemType e;
if(Q->front == Q->rear)//隊空
return ERROR;
p = Q->front->next;
e = p->data;
Q->front->next = p->next;
if(Q->rear == p)
Q->front=Q->rear;
free(p);
Q->count--;
3.顯示
先定義一個指針,顯示之後再逐漸爲空,直到指針移到空
QueuePtr p=Q->front->next;
printf("棧內容爲:\n");
while(p)
{
printf("%d ",p->data);
p = p->next;
}
代碼如下
/*
程序名稱:鏈棧的建立與基本操作
編譯環境:vs2010
最後修改:2019.8.3
作者:xuan
*/
#include<stdio.h>
#include<stdlib.h>
#define M 5
#define OK 1
#define ERROR 0
typedef int Status;
typedef int QElemType;
//定義結點
typedef struct QNode
{
QElemType data;
struct QNode* next;
}QNode,*QueuePtr;
//定義鏈隊列
typedef struct
{
QueuePtr front,rear;//隊頭指針和隊尾指針
int count;//計數器
}LinkQueue;
Status InitQueue(LinkQueue *Q);//初始化循環隊列
Status EnQueue(LinkQueue *Q);//入隊
Status DeQueue(LinkQueue *Q);//出隊
Status Display(LinkQueue *Q);//顯示
Status Clear(LinkQueue *Q);//置空
int main()
{
Status i;
LinkQueue Q;
int n=0;
InitQueue(&Q);
while(n!=-1)
{
printf(" \n");
printf(" 1.入隊 2.出隊 3.清空隊 -1.退出 \n");
scanf("%d",&n);
switch(n)
{
case 1:
i = EnQueue(&Q);
if(i == ERROR)
printf("失敗\n");
Display(&Q);
break;
case 2:
i = DeQueue(&Q);
if(i == ERROR)
printf("失敗\n");
Display(&Q);
break;
case 3:
Clear(&Q);
printf("操作後的順序棧:\n");
Display(&Q);
break;
}
}
return 0;
}
//初始化循環隊列
Status InitQueue(LinkQueue *Q)
{
QueuePtr head = (QueuePtr)malloc(sizeof(QNode));
head->next = NULL;
Q->front = head;
Q->rear = head;
Q->count = 0;
return OK;
}
//入隊
Status EnQueue(LinkQueue *Q)
{
QElemType x = 0;
printf("請輸入數據,-1時停止\n");
while(x != -1)
{
scanf("%d",&x);
if(x != -1)
{
QueuePtr s = (QueuePtr)malloc(sizeof(QNode));
s->data = x;
s->next = NULL;
Q->rear->next = s;
Q->rear = s;
Q->count++;
}
}
return OK;
}
//出隊
Status DeQueue(LinkQueue *Q)
{
QueuePtr p;
QElemType e;
if(Q->front == Q->rear)//隊空
return ERROR;
p = Q->front->next;
e = p->data;
Q->front->next = p->next;
if(Q->rear == p)
Q->front=Q->rear;
free(p);
Q->count--;
printf("出隊的元素爲:%d\n",e);
return OK;
}
//顯示
Status Display(LinkQueue *Q)
{
QueuePtr p=Q->front->next;
printf("棧內容爲:\n");
while(p)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
printf("隊列的長度爲:%d\n",Q->count);
return OK;
}
//置空
Status Clear(LinkQueue *Q)
{
Q->front = Q->rear;
Q->count = 0;
return OK;
}
運行結果
後記
上述代碼把鏈隊的各種操作柔和到一個方程裏面,以致於代碼有些龐大,但是在實際操作中還可以適當加減操作
以上就是鏈棧的表示和各種操作,喜歡的多多支持哦~