数据结构基本内容(第四篇:队列)

队列 Queue

FIFO

操作集:长度为MaxSize的队列Q  Queue,队列元素item  ElementType

  1. Queue CreatQueue( int MaxSize ):生成长度为MaxSize的空队列;

  2. int IsFullQ( Queue Q, int MaxSize ):判断队列Q是否已满;

  3. void AddQ( Queue Q, ElementType item ): 将数据元素item插入队列Q中;

  4. int IsEmptyQ( Queue Q ): 判断队列Q是否为空;

  5. ElementType DeleteQ( Queue Q ):将队头数据元素从队列中删除并返回。

队列的顺序存储实现

一个一维数组,队列头元素位置的变量front, 队列为元素位置的变量rear, 而堆栈由一个一位数组加上一个top.

队列的结构

```c

#define MaxSize <储存数据元素的最大个数>

struct QNode {

ElementType Data[ MaxSize ];

int rear;

int front;

};

typedef struct QNode *Queue;

```

循环队列

当front == rear时候, 空

rear指向这个队列实际的最后一个元素的位置,front是第一个元素的前一个. 加入一个元素的时候rear + 1, 删除一个元素的时候front + 1

使用额外标记 size或者tag

仅使用n-1个数组空间

* 创建队列

```c

Queue CreateQueue(int Maxsize)

{

Queue Q = (Queue)malloc(sizeof(struct QNode));

Q->Data = (ElementType)malloc(Maxsize * sizeof(ElementType));

Q->front = Q->rear = 0;

Q->Maxsize = Maxsize;

return Q;

}

```

* 入队列

用求余数函数,实现循环队列 例如 (5+1)%6 = 0, 放在第0位

```c

void AddQ( Queue PtrQ, ElementType item) {

if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) // front rear相邻

{

printf("队列满");

return;

}

PtrQ->rear = (PtrQ->rear+1)% MaxSize;

PtrQ->Data[PtrQ->rear] = item;

}

```

* 出队

```c

ElementType DeleteQ ( Queue PtrQ ) // front和rear相同

{

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

{

printf("队列空");

return ERROR;

}

else

{

PtrQ->front = (PtrQ->front+1)% MaxSize; // front往后移一位指向第一个元素

return PtrQ->Data[PtrQ->front];

}

}

```

队列的链式存储实现

链表结点结构

```c

struct Node{

ElementType Data;

struct Node *Next;

};

```

链表队列结构

```c

struct QNode

{

struct Node *rear; /* 指向队尾结点 */

struct Node *front; /* 指向队头结点 */

};

typedef struct QNode *Queue;

Queue PtrQ; // 包含front和rear的这个结构的指针PtrQ

```

* 出队

```c

ElementType DeleteQ ( Queue PtrQ )

{

struct Node *FrontCell;

ElementType FrontElem;

if ( PtrQ->front == NULL)

{

printf("队列空");

return ERROR;

}

FrontCell = PtrQ->front; // 找到队列的头个元素

if ( PtrQ->front == PtrQ->rear) /* 若队列只有一个元素 */

PtrQ->front = PtrQ->rear = NULL; /* 删除后队列置为空 */

else

PtrQ->front = PtrQ->front->Next;

FrontElem = FrontCell->Data;

free( FrontCell ); /* 释放被删除结点空间 */

return FrontElem;

}

```

应用: 多项式加法运算

算法思路:

两个指针P1和P2分别指向这两个多项式第一个结点,不断循环:

* P1->expon==P2->expon相同: 系数相加,若结果不为0,则作为结果多项式对应项

的系数。同时,P1和P2都分别指向下一项;

* P1->expon>P2->expon 这时p1大: 将P1的当前项存入结果多项式,并使P1指向下一项;

* P1->expon<P2->expon 这时p2大: 将P2的当前项存入结果多项式,并使P2指向下一项;

* 当某一多项式处理完时,将另一个多项式的所有结点依次复制到结果多项式中去。

```c

struct PolyNode //结构类型

{

int coef; // 系数

int expon; // 指数

struct PolyNode *link; // 指向下一个节点的指针

}

typedef struct PolyNode *Polynomial;

Polynomial P1, P2; // p1 p2都是这种结构的指针

```

实现

```c

Polynomial PolyAdd (Polynomial P1, Polynomial P2)

{

Polynomial front, rear, temp; // 结构多项式的头 尾.

int sum;

// 临时空结点点作为结果多项式的表头, front rear都指向这个空间点

rear = (Polynomial) malloc(sizeof(struct PolyNode));

front = rear; /* 由front 记录结果多项式链表头结点 */

while ( P1 && P2 ) /* 当两个多项式都有非零项(都不空)待处理时 */

switch ( Compare(P1->expon, P2->expon) ) // 比较两个指数

{

case 1: // p1大

// 系数和指素接到rear的后面

Attach( P1->coef, P1->expon, &rear);

P1 = P1->link;

break;

case -1: // p2大

Attach(P2->coef, P2->expon, &rear);

P2 = P2->link;

break;

case 0: //p1 = p2

sum = P1->coef + P2->coef;

// 判断sum不等于0

if ( sum ) Attach(sum, P1->expon, &rear);

P1 = P1->link;

P2 = P2->link;

break;

}

/* 将未处理完的另一个多项式的所有节点依次复制到结果多项式中去 */

// p1不空

for ( ; P1; P1 = P1->link )

Attach(P1->coef, P1->expon, &rear);

// p2 不空

for ( ; P2; P2 = P2->link )

Attach(P2->coef, P2->expon, &rear);

// rear 指向结果多项式的最后一项,现在结束了,把link设为NULL

rear->link = NULL;

// 释放临时结点

temp = front;

front = front->link; /*令front指向结果多项式第一个非零项 */

free(temp); /* 释放临时空表头结点 */

return front;

}

```

其中attach函数

```c

//传入系数和指数,以及最后一个结点的指针位置(指针的指针),于在本函数中需要改变当前结果表达式尾项指针的值,所以函数传递进来的是结点指针的地址,*pRear指向尾项

void Attach( int c, int e, Polynomial *pRear )

{

Polynomial P;

/* 申请新结点 */

P =(Polynomial)malloc(sizeof(struct PolyNode));

P->coef = c; /* 对新结点赋值 */

P->expon = e;

P->link=NULL;

/* 将P指向的新结点插入到当前结果表达式尾项的后面 */

(*pRear)->link = P;

*pRear = P; /* 修改pRear值 */

}

```

相关推荐
Miraitowa_cheems1 天前
LeetCode算法日记 - Day 82: 环形子数组的最大和
java·数据结构·算法·leetcode·决策树·线性回归·深度优先
Code_Shark1 天前
AtCoder Beginner Contest 426 题解
数据结构·c++·算法·数学建模·青少年编程
仰泳的熊猫1 天前
LeetCode:698. 划分为k个相等的子集
数据结构·c++·算法·leetcode
豐儀麟阁贵1 天前
4.5数组排序算法
java·开发语言·数据结构·算法·排序算法
2401_858286111 天前
OS36.【Linux】简单理解EXT2文件系统(2)
linux·运维·服务器·数据结构·文件系统·ext2
小羊学伽瓦1 天前
【Java数据结构】——常见力扣题综合
java·数据结构·leetcode·1024程序员节
linff9111 天前
hot 100 技巧题
数据结构·算法·leetcode
AI科技星1 天前
接近光速运动下的光速不变性:基于张祥前统一场论的推导与验证
数据结构·人工智能·经验分享·算法·计算机视觉
scx201310041 天前
20251025 分治总结
数据结构·c++·算法
while(1){yan}1 天前
数据结构之堆
数据结构·python·算法