将序列入队c语言,[数据结构 - 第4章] 队列之链队列(C语言实现)

一、什么是链队列?

**队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。**为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向尾结点,如下图所示:

8dd4505b714a9ffb9043ebff5eba3bc7.png

空队列时,front和rear都指向头结点,如下图所示。

945764634b5e0f0326ae44bb860461b2.png

链队列的结构为:

typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */

/* 结点结构 */

typedef struct QNode

{

ElemType data;

struct QNode *next;

}QNode;

/* 队列的链表结构 */

typedef struct

{

QNode *front; // 队头指针

QNode *rear; // 队尾指针

}LinkQueue;

二、基本操作

2.1 初始化操作

实现代码如下:

// 初始化链队列操作

Status initQueue(LinkQueue *Q)

{

Q->front = Q->rear = (Node *)malloc(sizeof(Node));

if (!Q->front)

return FALSE;

Q->front->next = NULL;

return TRUE;

}

2.1 入队操作

人队操作时,其实就是在链表尾部插入结点,如下图所示:

cb1946ac96cf078ff46fcea02218b0a9.png

实现代码如下:

// 入队操作

Status enQueue(LinkQueue *Q, ElemType e)

{

Node *s = (Node *)malloc(sizeof(Node));

if (!s)

return FALSE;

s->data = e;

s->next = NULL;

Q->rear->next = s;// 把拥有元素e的新结点s赋值给原队尾结点的后继

Q->rear = s; // 把当前的s设置为队尾结点,rear指向s

return TRUE;

}

2.3 出队操作

出队操作时,就是头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩一个元素时,则需将rear指向头结点,如下图所示:

a2891781860033c1fffa9caf4d1456b9.png

实现代码如下:

// 出队操作

Status deQueue(LinkQueue *Q, ElemType *e)

{

Node *p;

if (Q->front == Q->rear)

return FALSE;

p = Q->front->next; // 将欲删除的队头结点暂存给p,见图中①

*e = p->data; // 将欲删除的队头结点的值赋值给e

Q->front->next = p->next; // 将原队头结点的后继p->next赋值给头结点后继,见图中②

if (Q->rear == p) // 若队头就是队尾,则删除后将rear指向头结点,见图中③

Q->rear = Q->front;

free(p);

return TRUE;

}

2.4 遍历操作

实现代码如下:

// 遍历队列操作

Status tarverseQueue(const LinkQueue Q)

{

Node *p;

p = Q.front->next;

while (p)

{

printf("%d ", p->data);

p = p->next;

}

printf("\n");

return TRUE;

}

三、完整程序

#include

#include

#define TRUE 1

#define FALSE 0

#define MAXSIZE 20 /* 存储空间初始分配量 */

typedef int Status;

typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */

/* 结点结构 */

typedef struct Node

{

ElemType data;

struct Node *next;

}Node;

/* 队列的链表结构 */

typedef struct

{

Node *front; // 队头指针

Node *rear; // 队尾指针

}LinkQueue;

Status initQueue(LinkQueue *Q); // 初始化链队列操作

Status enQueue(LinkQueue *Q, ElemType e); // 入队操作

Status deQueue(LinkQueue *Q, ElemType *e); // 出队操作

Status tarverseQueue(const LinkQueue Q); // 遍历队列操作

Status destroyQueue(LinkQueue *Q); // 销毁队列操作

Status clearQueue(LinkQueue *Q); // 清空队列操作

Status isEmpty(const LinkQueue Q); // 判断是否为空队列

Status getHead(const LinkQueue Q, ElemType *e); // 获得队头元素

int getLength(const LinkQueue Q); // 获得队列的长度

// 初始化链队列操作

Status initQueue(LinkQueue *Q)

{

Q->front = Q->rear = (Node *)malloc(sizeof(Node));

if (!Q->front)

return FALSE;

Q->front->next = NULL;

return TRUE;

}

// 入队操作

Status enQueue(LinkQueue *Q, ElemType e)

{

Node *s = (Node *)malloc(sizeof(Node));

if (!s)

return FALSE;

s->data = e;

s->next = NULL;

Q->rear->next = s;// 把拥有元素e的新结点s赋值给原队尾结点的后继,见图中①

Q->rear = s; // 把当前的s设置为队尾结点,rear指向s,见图中②

return TRUE;

}

// 出队操作

Status deQueue(LinkQueue *Q, ElemType *e)

{

Node *p;

if (Q->front == Q->rear)

return FALSE;

p = Q->front->next; // 将欲删除的队头结点暂存给p,见图中①

*e = p->data; // 将欲删除的队头结点的值赋值给e

Q->front->next = p->next; // 将原队头结点的后继p->next赋值给头结点后继,见图中②

if (Q->rear == p) // 若队头就是队尾,则删除后将rear指向头结点,见图中③

Q->rear = Q->front;

free(p);

return TRUE;

}

// 遍历队列操作

Status tarverseQueue(const LinkQueue Q)

{

Node *p;

p = Q.front->next;

while (p)

{

printf("%d ", p->data);

p = p->next;

}

printf("\n");

return TRUE;

}

// 销毁队列操作

Status destroyQueue(LinkQueue *Q)

{

while (Q->front)

{

Q->rear = Q->front->next;

free(Q->front);

Q->front = Q->rear;

}

return TRUE;

}

// 清空队列操作

Status clearQueue(LinkQueue *Q)

{

Node *p;

Node *q;

Q->rear = Q->front;

p = Q->front->next;

Q->front->next = NULL;

while (p)

{

q = p;

p = p->next;

free(q);

}

return TRUE;

}

// 判断是否为空队列

Status isEmpty(const LinkQueue Q)

{

return Q.front == Q.rear ? TRUE : FALSE;

}

// 获得队头元素

Status getHead(const LinkQueue Q, ElemType *e)

{

Node *p;

if (Q.front == Q.rear)

return FALSE;

p = Q.front->next;

*e = p->data;

return TRUE;

}

// 获得队列的长度

int getLength(const LinkQueue Q)

{

int i = 0;

Node *p;

p = Q.front;

while (Q.rear != p)

{

i++;

p = p->next;

}

return i;

}

int main()

{

LinkQueue Q;

// 初始化队列

initQueue(&Q);

// 入队操作

for (int i = 0; i < 4; i++)

enQueue(&Q, i);

printf("入队操作(0、1、2、3)! \n\n");

// 出队操作

ElemType d;

deQueue(&Q, &d);

printf("删除的元素是%d \n\n", d);

// 遍历队列

printf("遍历队列: ");

tarverseQueue(Q);

printf("\n");

// 判断是否为空队列

printf("现在队列空否? %u (1:空 0:否)\n\n", isEmpty(Q));

// 获得队列的长度

printf("队列长度为: %d \n\n", getLength(Q));

// 获得队头元素

getHead(Q, &d);

printf("队头元素是%d \n\n", d);

return 0;

}

输出结果如下图所示:

b6a369aef4420339b6870f28858c3f72.png

参考:

《大话数据结构 - 第4章》 栈与队列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值