赞
踩
队列是运算受限的线性表,和线性表一样也是线性结构,只不过插入只能在队尾插入称为入队,删除只能在队头删除称为出队,和日常生活中的排队顺序一样,是先进先出(FIFO)的线性表。队列存储结构分为顺序存储和链式存储,本文主要介绍 队列的链式存储.
优点:
动态扩容:链式存储结构可以根据实际需求动态扩容,不需要预先确定队列的最大长度,能够更灵活地处理不确定长度的队列。
不会出现溢出问题:链式存储结构不会出现循环队列的溢出问题,可以无限扩展,适合处理大规模数据。
缺点:
占用额外的存储空间:链式存储结构需要额外的指针空间来存储节点之间的关系,占用了额外的存储空间。
**操作复杂:**链式存储结构在插入和删除操作时需要涉及指针的操作,相对于循环顺序存储结构来说,操作可能更加复杂,时间复杂度为O(n)。
#include <stdio.h> #include <malloc.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; typedef int DataType; typedef struct QNode { DataType data; //定义结点的数据域 struct QNode *next; //定义结点的指针域 }QNode; typedef struct{ QNode *front,*rear; //定义队列的头指针和尾指针 }LinkQueue;
Status InitQueue(LinkQueue *Q)
{
Q->front =Q->rear = (QNode *)malloc(sizeof(QNode));
Q->front->next = NULL; //带头结点的链队列
// Q->front =Q->rear =NULL; 不带头结点
return OK;
}
Status DestroyQueue(LinkQueue *Q)
{
while(Q->front)
{
Q->rear = Q->front->next; //这里Q->rear 只是当作一个中继指针使用,不做尾指针,也可用一个新的指针
free(Q->front);
Q->front = Q->rear;
}
return OK;
}
Status IsEmpty(LinkQueue *Q)
{
return Q->front == Q->rear; //带头结点的
// Q-front == NULL; 不带头结点
}
1.链队不需要考虑队满情况,申请一个新结点
2.新结点数据域赋值,因为在队尾插入,所以指针域next赋空.
3.队尾指针的next域指向新结点
4.修改队尾指针指向新结点
//入队
Status EnQueue(LinkQueue *Q, DataType x)
{
QNode *p = (QNode *)malloc(sizeof(QNode));
if(!p)
exit(OVERFLOW);
p->data = x;
p->next =NULL;
Q->rear->next = p;
Q->rear = p;
return OK;
/* 不带头节点的话,要判断是否为空队列,如果空队列,要对front和rear指针都进行修改*/
}
1.判断队列是否为空,为空则不能出队
2.申请一个结点做为中继结点指向出队元素
3. 出队元素
4. 修改队头指针指向新元素
5. 判断 队中是不是只有这一个元素,如果是修改队尾元素指向队头
6. 清除掉中继结点的内存
Status DeQueue(LinkQueue *Q,DataType *x) { QNode *p; if(IsEmpty(Q)) { printf("队空,不能出队!"); return ERROR; } p = Q->front->next; // p =Q ->front 不带头结点 *x = p->data; Q->front->next =p->next; //修改队头指针指向新元素 Q->front = p->next;不带头结点的 if(Q->rear == p) //p->next == NULL; Q->rear = Q->front; //Q->rear = Q->front =NULL; 不带头结点的 free(p); return OK; }
//取队头元素
DataType GetFront(LinkQueue *Q , DataType *x)
{
if(IsEmpty(Q))
{
printf("队空,不能取队头元素!");
return ERROR;
}
*x = Q->front->next->data; // *x = Q->front->data 不带头结点
return OK;
}
void ShowQueue(LinkQueue *Q)
{
QNode *p = Q->front->next;
if (!p)
printf("队空无元素");
else
{
printf("从队头起队中各元素为:");
while (p)
{
printf("%5d", p->data);
p = p->next;
}
}
}
#include <stdio.h> #include <stdlib.h> #include <malloc.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; typedef int DataType; typedef struct QNode { DataType data; //定义结点的数据域 struct QNode *next; //定义结点的指针域 } QNode; typedef struct { QNode *front, *rear; //定义队列的头指针和尾指针 } LinkQueue; //初始化 Status InitQueue(LinkQueue *Q) { Q->front = Q->rear = (QNode *)malloc(sizeof(QNode)); Q->front->next = NULL; //带头结点的链队列 return OK; } //销毁 Status DestroyQueue(LinkQueue *Q) { while (Q->front) { Q->rear = Q->front->next; free(Q->front); Q->front = Q->rear; } return OK; } // 判队空 Status IsEmpty(LinkQueue *Q) { return Q->front == Q->rear; //带头结点的 } //入队 Status EnQueue(LinkQueue *Q, DataType x) { QNode *p = (QNode *)malloc(sizeof(QNode)); if (!p) exit(OVERFLOW); p->data = x; p->next = NULL; Q->rear->next = p; Q->rear = p; return OK; } //出队 Status DeQueue(LinkQueue *Q, DataType *x) { QNode *p; if (IsEmpty(Q)) { printf("队空,不能出队!"); return ERROR; } p = Q->front->next; *x = p->data; Q->front->next = p->next; if (Q->rear == p) Q->rear = Q->front; free(p); return OK; } //取队头元素 DataType GetFront(LinkQueue *Q, DataType *x) { if (IsEmpty(Q)) { printf("队空,不能取队头元素!"); return ERROR; } *x = Q->front->next->data; return OK; } //显示队中元素 void ShowQueue(LinkQueue *Q) { QNode *p = Q->front->next; if (!p) printf("队空无元素"); else { printf("从队头起队中各元素为:"); while (p) { printf("%5d", p->data); p = p->next; } } } void MenuQueue() { /*显示菜单子函数*/ printf("\n 队列子系统"); printf("\n=================================================="); printf("\n| 1——初始化队列 |"); printf("\n| 2——销 毁 队列 |"); printf("\n| 3——判队空 |"); printf("\n| 4——入队操作 |"); printf("\n| 5——出队操作 |"); printf("\n| 6——求队头元素 |"); printf("\n| 7——显示队中所有元素 |"); printf("\n| 0——返回 |"); printf("\n=================================================="); printf("\n请输入菜单号(0-7): "); } int main() { int i, n, flag, choice; LinkQueue Q; DataType x; do { MenuQueue(); scanf("%d", &choice); switch (choice) { case 1: if (InitQueue(&Q) == OK) printf("队列初始化成功!"); break; case 2: if (DestroyQueue(&Q) == OK) printf("队列已销毁!"); break; case 3: if (IsEmpty(&Q) == TRUE) printf("队列为空!"); else printf("队列非空!"); break; case 4: printf("请输入要入队元素的个数:"); scanf("%d", &n); printf("请输入 %d 个入队的整数,中间用空格隔开: ", n); for (i = 0; i < n; i++) { scanf("%d", &x); flag = EnQueue(&Q, x); } if (flag == OK) printf("入队成功!"); else printf("入队失败!"); break; case 5: printf("请输入要出队的元素个数:"); scanf("%d",&n); printf("出队的元素顺序依次为:"); for(i=0;i<n;i++) { flag=DeQueue(&Q,&x); printf("%5d",x); } if (flag == OK) printf("\n出队成功"); else printf("\n出队失败"); break; case 6: if (GetFront(&Q, &x) == OK) printf("队头元素为: %d", x); break; case 7: ShowQueue(&Q); break; } } while (choice != 0); return 0; }
主要先考虑带不带头结点,然后以链表的思想进行操作队头和队尾,插入删除时间复杂度都是O(1)
带头结点 队头结点 Q->front->next
不带头结点 Q->front
敬请各位大佬批评指正 日后也会持续更新数据结构相关内容,互相学习声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。