一、单链队列的链式存储结构
相关代码下载链接:http://download.csdn.net/detail/shengshengwang/8141633
队列是操作受限的线性表,只允许在队尾插入元素,在队头删除元素。对于链队列结构,为了便于插入元素,设立了队尾指针,这样插入元素的操作便与队列长度无关。存储结构,如下所示:
typedef int QElemType; typedef struct QNode { QElemType data; QNode *next; } *QueuePtr; struct LinkQueue { QueuePtr front, rear; // 队头、队尾指针 };
二、单链队列的链式存储结构的基本操作
(1)构建队列
void InitQueue(LinkQueue &Q) { // 构造一个空队列Q Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); // 生成头结点 if(!Q.front) // 生成头结点失败 exit(3); Q.front->next = NULL; // 头结点的next域为空 }
(2)销毁队列
void DestroyQueue(LinkQueue &Q) { // 销毁队列Q(无论空否均可) while(Q.front) // Q.front不为空 { Q.rear = Q.front->next; // Q.rear指向Q.front的下一个结点 free(Q.front); // 释放Q.front所指结点 Q.front = Q.rear; // Q.front指向Q.front的下一个结点 } }
(3)队列判空
int QueueEmpty(LinkQueue Q) { // 若队列Q为空队列,则返回TRUE;否则返回FALSE if(Q.front->next == NULL) return 1; else return 0; }
(4)插入队列
void EnQueue(LinkQueue &Q, QElemType e) { // 插入元素e为队列Q的新的队尾元素 QueuePtr p; p = (QueuePtr)malloc(sizeof(QNode)); // 动态生成新结点 if(!p) exit(3); // 若分配堆内存失败,则退出 p->data = e; // 将值e赋给新结点 p->next = NULL; // 新结点的指针域为空 Q.rear->next = p; // 原队尾结点的指针指向新结点 Q.rear = p; // 尾指针指向新结点 }
(5)删除队列
int DeQueue(LinkQueue &Q, QElemType &e) { // 若队列Q不空,删除Q的队头元素,用e返回其值 // 并返回OK;否则返回ERROR QueuePtr p; if(Q.front == Q.rear) // 队列空 return 0; p = Q.front->next; // p指向队头结点 e = p->data; // 将队头元素的值赋给e Q.front->next = p->next; // 头结点指向下一个结点 if(Q.rear == p) // 删除的是队尾结点 Q.rear = Q.front; // 修改队尾指针指向头结点(空队列) free(p); // 释放队头结点 return 1; }
(6)取得队列首元素
int GetHead(LinkQueue Q, QElemType &e) { // 若队列Q不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR QueuePtr p; if(Q.front == Q.rear) // 队列空 return 0; p = Q.front->next; // p指向队头结点 e = p->data; // 将队头元素的值赋给e return 1; }
(7)遍历队列
void print(QElemType e) { printf("%d ", e); } void QueueTraverse(LinkQueue Q, void(*visit)(QElemType)) { // 从队头到队尾依次对队列Q中的每个元素调用visit() QueuePtr p = Q.front->next; // p指向队头结点 while(p) // p指向结点 { visit(p->data); // 对p所指元素调用visit() p = p->next; } printf("\n"); }
三、检验基本操作的主函数
void main() { QElemType d; LinkQueue q; InitQueue(q); // 构造空队列q,失败则退出 // 依次入队3个元素 EnQueue(q, -5); EnQueue(q, 5); EnQueue(q, 10); printf("队列的元素依次为:"); QueueTraverse(q, print); GetHead(q, d); DeQueue(q, d); printf("队列的元素依次为:"); QueueTraverse(q, print); }
四、队列抽象数据类型定义
ADT Queue{ 数据对象:D={ai|ai∈ElemSet, i=1,2, …,n, n≥0} 数据关系:R1={<ai-1,ai>|ai-1,ai∈D, i=1,2, …,n } 约定a1为队列头,an为队列尾。 基本操作: InitQueue( &Q ) 操作结果:构造一个空队列Q。 DestroyQueue ( &Q ) 初始条件:队列Q已存在。 操作结果:销毁队列Q。 ClearQueue ( &Q ) 初始条件:队列Q已存在。 操作结果:将Q清为空队列。 QueueEmpty( Q ) 初始条件:队列Q已存在。 操作结果:若Q为空队列,则返回TRUE,否则返回FALSE。 QueueLength( Q ) 初始条件:队列Q已存在。 操作结果:返回Q的数据元素个数,即队列的长度。 GetHead( Q, &e ) 初始条件:队列Q已存在且非空。 操作结果:用e返回Q的队头元素。 EnQueue( &Q, e ) 初始条件:队列Q已存在。 操作结果:插入元素e为Q的新的队尾元素。 DeQueue( &Q, &e ) 初始条件:队列Q已存在且非空。 操作结果:删除Q的队头元素,并用e返回其值。 QueueTraverse( Q, visit() ) 初始条件:队列Q已存在且非空。 操作结果:从队头到队尾依次对Q的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。 }ADT Queue
原文地址:http://blog.csdn.net/ssw_1990/article/details/40980583