zoukankan      html  css  js  c++  java
  • 队列

      队列是一种只允许在一端进行插入,而在另一端进行删除的线性表,它是一种操作受限制的线性表,在该表中只允许插入的一端称为队尾(rear),二另一端只允许删除的一端称为队首(front)。

    一、队列的顺序存储

      队列的顺序存储结构就可以称为顺序队列,也就是利用一组地址连续的存储单元将元素依次存放在队列中。如图:

    由上图可知可以先写出其数据类型

    typedef struct queue
    {
    	ElemType elem[MAXSIZE];
    	int front;
    	int rear;
    }queue;
    

      其中的MAXSIZE指明的是队列中的存储容量的大小,队列初始化时,将队尾的索引与队首的索引都相同且置为-1

    void Init_queue(queue *Q)
    {
    	Q->front=-1;
    	Q->rear=-1;
    }
    

    这个时候就可以进行一系列的操作了,如下:

    #include<stdio.h>
    #define MAXSIZE 10
    typedef int ElemType;
    
    typedef struct queue
    {
    	ElemType elem[MAXSIZE];
    	int front;
    	int rear;
    }queue;
    
    void Init_queue(queue *Q)
    {
    	Q->front=-1;
    	Q->rear=-1;
    }
    
    int Empty_queue(queue Q)
    {
    	if(Q.front==Q.rear)
    		return 1;
    	else
    		return 0;
    }
    
    int Full_queue(queue Q)
    {
    	if(Q.rear>=MAXSIZE-1)
    		return 1;
    	else
    		return 0;
    }
    
    int QueueLength(queue Q)
    {
    	return Q.rear-Q.front;
    }
    
    int EnQueue(queue *Q,ElemType x)
    {
    	if(Full_queue(*Q)) 
    		return 0;
    	Q->elem[++Q->rear]=x;
    	return 1;
    }
    
    int DeQueue(queue *Q,ElemType *x)
    {
    	if(Empty_queue(*Q))
    		return 0;
    	else
    	{
    		*x=Q->elem[++Q->front];
    		return 1;
    	}
    }
    
    void QueuePrint(queue Q)
    {
    	int i;
    	printf("队列的元素为: ");
    	for(i=Q.front+1;i<=Q.rear;i++)
    		printf("%d ",Q.elem[i]);
    	printf("
    队列的长度为:%d
    ------over--------
    ",QueueLength(Q));
    
    }
    
    void main()
    {
    	queue Q;
    	Init_queue(&Q);
    	int n,i=0;	//n是要入栈的元素的个数
    	printf("请输入要入栈的元素的个数: ");
    	scanf("%d",&n);
    	while(n>MAXSIZE || n<1){
    		printf("队列容量有限(默认为%d),%d不符合要求,请重新输入
    ",MAXSIZE,n);
    	}
    	ElemType x;
    	printf("请分别输入入栈的元素:
    ");
    	for(i=0;i<n;i++)
    	{
    		scanf("%d",&x);
    		EnQueue(&Q,x);
    	}
    	QueuePrint(Q);
    	//出队操作
    	for(i=1;i<n;i++)
    	{
    		DeQueue(&Q,&x);
    		printf("第%d次出队的元素是:%d
    ",i,x);
    		QueuePrint(Q);
    	}
    }
    

      运行结果如图:

     二、循环队列

      在顺序队列中,当队尾指针指向了队列中的最后一个元素的位置的时候,此时若有元素入队列,就会发生“溢出”,此时假设即便有两个元素出队了,虽然有两个看位置,但是其队尾指针的位置与队首指针之间没有关系,所以还是无法腾出位置给其他元素,可以称这种现象为假溢出现象。

    解决该办法有两种:

      (1)、采用平移的方法,当发生假溢出的时候将整个队列平移至存储区的首部,然后在插入元素。这样做的需要移动大量元素,因而效率是很低的。

      (2)、将顺序队列的存储区假设为一个环状的空间,如图:


    程序实现如下:

    #include<stdio.h>
    #include<stdlib.h>
    #define N 6
    typedef int ElemType;
    
    typedef struct queue
    {
    	ElemType *data;
    	int front;
    	int rear;
    }queue;
    
    void Init_queue(queue *Q)
    {
    	//开辟连续的存储空间作为队列的存储容量
    	Q->data=(ElemType *)malloc(N*sizeof(ElemType));
    	Q->front=-1;
    	Q->rear=-1;
    }
    
    int Empty_queue(queue Q)
    {
    	if(Q.front==Q.rear)
    		return 1;
    	else
    		return 0;
    }
    
    int Full_queue(queue Q)
    {
    	if((Q.rear+1)%N==Q.front)
    	{
    		printf("队列已满,不能再进行入队操作了啊!
    ");
    		return 1;
    	}
    	else
    		return 0;
    }
    
    int Length_queue(queue Q)
    {
    	return (Q.rear+N-Q.front)%N;
    }
    
    int En_queue(queue *Q,ElemType x)
    {
    	if(Full_queue(*Q))
    		return 0;
    	Q->rear=(Q->rear+1)%N;
    	Q->data[Q->rear]=x;
    	return 1;
    }
    
    int De_queue(queue *Q,ElemType *x)
    {
    	if(Full_queue(*Q))
    		return 0;
    	Q->front=(Q->front+1)%N;
    	*x=Q->data[Q->front];
    }
    
    void QueuePrint(queue Q)
    {
    	int i;
    	printf("队列的元素为: ");
    	if(Q.rear<Q.front)
    		Q.rear+=N;
    	for(i=Q.front+1;i<=Q.rear;i++)
    		printf("%d ",Q.data[i%N]);
    	printf("
    队列的长度为:%d
    ------over--------
    ",Length_queue(Q));
    }
    
    void main()
    {
    	queue Q;
    	Init_queue(&Q);
    	int n,i=0;	//n是要入栈的元素的个数
    	printf("请输入要入栈的元素的个数: ");
    	scanf("%d",&n);
    	while(n>N || n<1){
    		printf("队列容量有限(默认为%d),%d不符合要求,请重新输入
    ",N,n);
    	}
    	ElemType x;
    	printf("请分别输入入栈的元素:
    ");
    	for(i=0;i<n;i++)
    	{
    		scanf("%d",&x);
    		En_queue(&Q,x);
    	}
    	QueuePrint(Q);
    
    	/*现在模拟已经输入队列四个元素,出队列两个元素后,如果是前面的顺序队列,
    	则只能继续入對两个元素,若是循环队列,则可以继续入队四个元素*/
    	
    	//出队两个元素
    	for(i=0;i<=1;i++)
    	{
    		De_queue(&Q,&x);
    		printf("第%d次出队的元素是:%d
    ",i+1,x);
    		QueuePrint(Q);
    	}
    	//入四个元素到队列中去
    	for(i=6;i<=9;i++)
    		En_queue(&Q,i);
    	QueuePrint(Q);
    
    }
    

    运行结果如图:

     三、队列的链式存储

      在一个链队列中,设定两个指针(头指针和尾指针),分别指向队列的头和尾,类比线性表,给队列链添加一个头结点,并设定头指针指向头结点。结构如图:

    即队列链表的结构体如下:

    typedef struct Qnode{
    	ElemType data;
    	struct Qnode *next;
    }Qnode;
    typedef struct {
    	Qnode *front;
    	Qnode *rear;
    }
    

    类比上面的图片可以写出如下形式的完整代码:

    #include<stdio.h>
    #include<stdlib.h>
    typedef int ElemType;
    typedef struct Qnode{
    	ElemType data;
    	struct Qnode *next;
    }Qnode;
    typedef struct {
    	Qnode *front;
    	Qnode *rear;
    }LinkQueue;
    void Init_queue(LinkQueue *Q)
    {
    	Q->front=Q->rear=(Qnode*)malloc(sizeof(Qnode));
    	if(!(Q->front)){
    		printf("头结点的存储空间开辟失败!
    ");
    		exit(0);
    	}
    	Q->front->next=NULL;
    }
    
    void Destory_Queue(LinkQueue *Q)
    {
    	while(Q->front)
    	{
    		Q->rear=Q->front->next;
    		free(Q->front);
    		Q->front=Q->rear;
    	}
    	printf("队列已经被销毁了!
    ");
    }
    
    int Empty_queue(LinkQueue Q)
    {
    	if(Q.front==Q.rear)
    		return 1;
    	else
    		return 0;
    }
    
    
    int QueueLength(LinkQueue Q)
    {
    	Qnode *p=Q.front;
    	int n=0;
    	while(p!=Q.rear)
    	{
    		n++;
    		p=p->next;
    	}
    	return n;
    }
    
    ElemType Get_head(LinkQueue Q)
    {
    	if(Q.front!=Q.rear)
    		return Q.front->next->data;
    	else
    		return 0;
    }
    
    void En_queue(LinkQueue *Q,ElemType x)
    {
    	Qnode *p=(Qnode*)malloc(sizeof(Qnode));
    	if(!p)
    	{
    		printf("新节点开辟失败!
    ");
    		exit(0);
    	}
    	p->data=x;
    	p->next=NULL;
    	if(Q->rear==NULL)
    		//头结点,起始时头结点和尾结点指向同一个元素
    		Q->rear=p;
    	else
    	{
    		Q->rear->next=p;
    		Q->rear=p;
    	}
    }
    
    void De_queue(LinkQueue *Q,ElemType *x)
    {
    	Qnode *p;
    	if(Q->front!=Q->rear)
    	{
    		//队列非空
    		p=Q->front->next;	//Q->front代表的是链表的头结点,是一个空节点
    		Q->front->next=p->next;
    		*x=p->data;
    		if(Q->rear==p)
    			Q->rear=Q->front;
    		free(p);
    	}
    
    }
    
    void Print_queue(LinkQueue Q)
    {
    	Qnode *p;
    	printf("队列中的元素如下:
    ");
    	if(Q.front==NULL){
    		printf("队列为空!没有元素。");
    		return;
    	}
    	p=Q.front->next;
    	while(p)
    	{
    		printf("%d	",p->data);
    		p=p->next;
    	}
    	printf("
    队列的长度为:%d
    ",QueueLength(Q));
    }
    
    void main()
    {
    	LinkQueue Q;
    	Init_queue(&Q);
    	int n,i;
    	ElemType x,e;
    	printf("请输入要入队的元素的个数:");
    	scanf("%d",&n);
    	printf("请分别输入要入队的元素的值:
    ");
    	for(i=0;i<n;i++)
    	{
    		scanf("%d",&x);
    		En_queue(&Q,x);
    	}
    	Print_queue(Q);
    	//元素出队
    	De_queue(&Q,&x);
    	Print_queue(Q);
    	e=Get_head(Q);
    	printf("此时出队的元素是 %d ,现在队首元素是 %d .
    ",x,e);
    	//销毁队列
    	Destory_Queue(&Q);
    }
    

     运行结果如图:

  • 相关阅读:
    【Jenkins】jenkins 配置腾讯企业邮箱
    Monkey 用户指南(译)
    Windows,easygui 安装
    python笔记:list--pop与remove的区别
    递归--Java_汉诺塔
    appium安装 For windows
    【web开发--js学习】functionName 如果是一个属性值,函数将不会被调用
    python爬取煎蛋网图片
    pv&pvc
    docker
  • 原文地址:https://www.cnblogs.com/helloworldcode/p/6816876.html
Copyright © 2011-2022 走看看