您的位置:首页 > 理论基础 > 数据结构算法

数据结构(1)队列

2016-05-04 20:41 302 查看
队列定义:只允许在一端进行插入,在一端进行删除的线性表。

生活中的很多例子都可以用队列来体现,如买饭排队。

同样类似于栈,队列在电脑中的储存方式也分为两种,顺序储存和链式储存。


[b]顺序储存:


[/b]

顺序储存结构的情况如下,我们在使用前要确定队列的大小,通过建立数组来储存队列的元素。建立两个指针

来标示队头和队尾,添加元素和删除元素即为移动队头或是队尾。虽然建立方便,但是局限在于无法储存更多的

元素。





进一步的优化,我们产生了循环队列。就是当队尾指针指向了数组中的最后一个元素,即将溢出的时候,我

们就把队尾指向数组的第一个元素,前提是此时的队头指针已经发生了移动。

链式储存:

无论怎样,我们都可以看出顺序储存队列对于长度方面的不足,即使是加入了循环队列仍然无法满足需求。

因此我们加入了队列的链式储存结构。

队列的链式储存结构就是单向链表,但是我们在使用它的时候保持了头出尾加的原则。

为了更加清晰的说明队列的链式储存结构,在这里引入一道程序设计题。

题目:关于排队打饭的问题



首先输入一个整数m(m<10000),代表当前有m个人

第二行输入m个数,代表每个人的编号

第三行输入一个整数n(n<10000),代表队列变动和询问一共n次

以后n行,JOIN X(或 J X)表示编号为X(保证与以前的编号不同)的人加入;

ASK Z(或 A Z)(Z小于当前队列长度)表示询问第Z个位置上的人的编号;

FINISH D(或 F D)表示有D个人买完饭离开了;

LENGTH(或 L)表示询问队列的长度 。保证所有数据在int 范围内。同时打印队列。


使用链式储存结构编写程序,如下:

[b]#include<stdio.h>

#include<stdlib.h>

/*建立每个节点的格式*/

struct Node

{

int data;

struct Node *next;

};

/*有两个指针节点构成的队列*/

struct queue

{

struct Node *front;

struct Node *rear;

};

/*初始化一个队列*/

void initqueue(struct queue *hp)

{

hp->front=hp->rear=NULL;

}

/*向队列中储存一个新的数据x*/

void inqueue(struct queue *hp,int x)

{

struct Node *newNode;/*建立一个指针节点指向刚刚建立的节点*/

newNode=malloc(sizeof(struct Node));

if(newNode==NULL)

{

printf("内存分配失败!");

exit(1);

}

newNode->data=x;/*将x的值赋给节点的值域*/

newNode->next=NULL;/*新加入的节点在最后,因此所指向为空*/

/*队列为空,则即为队首节点也为队尾节点*/

if(hp->rear==NULL)

{

hp->front=hp->rear=newNode;

}

/*若队列并非为空,则修改队尾节点的指针域和队尾指针,使之指向新的队尾节点*/

else

{

hp->rear=hp->rear->next=newNode;

}

}

/*从队列中删除一个元素*/

int delqueue(struct queue *hp)

{

struct Node *p;

int temp;

/*若队列为空则停止运行*/

if(hp->front==NULL)

{

printf("队列为空,无法删除元素!");

exit(1);

}

temp=hp->front->data;

p=hp->front;

hp->front=p->next;

if(hp->front==NULL)

{

hp->rear=NULL;

}

free(p);

return temp;

}

/*读取队首元素*/

int peekqueue(struct queue *hp)

{

/*若链队为空则停止运行*/

if(hp->front==NULL)

{

printf("队列为空,无法删除!");

exit(1);

}

return hp->front->data; /*返回队首元素*/

}

/*检查链队是否为空,若为空则返回i1,否则返回0*/

int emptyqueue(struct queue *hp)

{

/*判断队首或队尾任一个指针是否为空即可*/

if(hp->front==NULL)

{

return 1;

}

else

{

return 0;

}

}

/*清除链队中的所有元素*/

void clearqueue(struct queue *hp)

{

struct Node *p=hp->front;/*队首指针赋给p*/

/*依次删除队列的每一个结点,最后使队首指针为空*/

while(p!=NULL)

{

hp->front=hp->front->next;

free(p);

p=hp->front;

}

/*循环结束后队首指针已经为空*/

hp->rear=NULL;/*使队尾指针为空*/

}

/*遍历队列中的元素*/

void lookqueue(struct queue *hp)

{

int i=0;

struct Node *q=hp->front,*p=hp->front;/*队首指针赋给p*/

while(p!=NULL)

{

printf("%2d",q->data);

p=p->next;

q=p;

i++;

}

printf("\n");

printf("队列长度为%d\n",i);

}

/*查找某个位置所存放的元素*/

void findqueue(struct queue *hp,int x)

{

int i=1;

struct Node *q=hp->front,*p=hp->front;/*队首指针赋给p*/

while(p!=NULL)

{

if(i==x)

{

printf("%d\n",q->data);

}

p=p->next;

q=p;

i++;

}

}

void main()

{

int n, m, i, num[10000] ;

int x, y, z, d ;

int p = 1, c = 0 ;

char str[50];

struct queue q;

initqueue(&q);

scanf("%d",&n);

for(i=0;i<n;i++)

{

scanf("%d",&x);

inqueue(&q,x);

}

scanf("%d", &n) ;/*进行操作的次数*/

c = m;

while(n--)

{

scanf("%s", str) ;

if(strcmp(str,"JOIN") == 0||strcmp(str,"J")==0)/*添加新的元素*/

{

scanf("%d", &x) ;

inqueue(&q,x);

}

if(strcmp(str, "ASK") == 0||strcmp(str,"A")==0)/*通过位置查找存放元素*/

{

scanf("%d", &z) ;

findqueue(&q,z);

}

if(strcmp(str, "LENGTH") == 0||strcmp(str,"L")==0)/*显示当前队列的长度*/

{

lookqueue(&q);

}

if(strcmp(str, "FINISH") == 0||strcmp(str,"F")==0)/*删除队列中的元素*/

{

scanf("%d", &d) ;

for(i=1;i<=d;i++)

delqueue(&q);

}

}

}

这道题如果使用顺序储存结构会更加的简单,代码也会更加的短小,但是仍建议使用链式储存结构养成好习惯。
[/b]

顺序储存结构:

#include<stdio.h>

#include<string.h>

void main()

{

int n, m, i, num[10000] ;

int x, y, z, d ;

int p = 1, c = 0 ;

char str[100] ;

scanf("%d", &m);/*初始有几个结点*/

for(i = 1 ; i <= m; i++)

scanf("%d", &num[i]) ;/*每个结点所存放的数据*/

scanf("%d", &n) ;/*进行操作的次数*/

c = m;

while(n--)

{

scanf("%s", str) ;

if(strcmp(str,"JOIN") == 0||strcmp(str,"J")==0)/*添加新的元素*/

{

scanf("%d", &x) ;

num[++c] = x ;

}

if(strcmp(str, "ASK") == 0||strcmp(str,"A")==0)/*通过位置查找存放元素*/

{

scanf("%d", &z) ;

printf("%d\n", num[p+z-1]) ;

}

if(strcmp(str, "LENGTH") == 0||strcmp(str,"L")==0)/*显示当前队列的长度*/

{

printf("%d\n", c-p+1) ;

}

if(strcmp(str, "FINISH") == 0||strcmp(str,"F")==0)/*删除队列中的元素*/

{

scanf("%d", &d) ;

p = p + d ;

}

}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: