数据结构(1)队列(C语言版)

    队列定义:只允许在一端进行插入,在一端进行删除的线性表。

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

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

    顺序储存:

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

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

元素。

   

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

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

       链式储存:

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

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

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

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


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

首先输入一个整数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 范围内。同时打印队列。


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

#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);
        }
}

}


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

顺序储存结构:


#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 ;
        }
}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

daijingxin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值