队列(C语言版)

                                           队列

  • 队列既可以用链式结构存储也可以用顺序结构存储,

                       【---跟栈相反的是,栈我们一般用顺序表实现,而队列我们常用链表来实现,简称为链队列 --】 

第一种:顺序队列:

                   老规矩,先看它长得易接受不^V^ ( 自己画的图有些丑~^~) :

  1.  队头不动,只有rear移动

                                                  加入新节点步骤 :Q[rear]=data    rear++;

                                                  删除新节点步骤: 需从第一个位置开始,大量移动元素,所有数据向后移动一位                                                                    for(int i=front;i<rear;i++){                                                                                                                                                             Q.[i]=Q.[i+1];  

  2.                                               然后rear--;                                                                                                                           

    头不动

     

  3. 队头front与rear都可以移动

                                                      加入新节点步骤 :Q[rear]=data    rear++;

                                                      删除新节点步骤:front++;

头游标可移动

      【注意】:第二种头可动的情况第四个图出现了传说中的“假溢出”de问题:

简单来说就是,J放进队列尾部后,rear指针要继续后移,但此时已不能继续指向下一个空间了。

但是:如图所示,明明front下面还有那么多可以利用的空间啊,因此被称为“假溢出”。而真正的溢出人家长得是很丰满的好吧!!!

那么小伙伴们思考下如何打"假"呢???  后面第三种队列将会解决这个问题。不要急,骚等啦~

真溢出(画图好累~~~~(>_<)~~~~)

 

第二种:链队列:

链队列的颜值

                             A:  定义方式(有些特别O)

typedef struct Qnode{
	Elemtype data;
	struct Qnode *next;
}Qnode,*Qlinklist; 

typedef struct LinkQ{
	Qlinklist front,rear;//定义队列的头指针front尾指针rear 
}LinkQ;

//此队列规定在队头出列(删除),在队尾入列(插入)

                             B:创建(初始化)链表

int initQueue(LinkQ *q){
	q->front=q->rear=(Qlinklist)malloc(sizeof(Qnode));//初始化时首尾合一,链表空
	if(!q->front){
		exit(0);
	}
	q.front->next=NULL; //头节点即尾结点,指针域都设置为NULL
	return 1;
} 

                             C:插入操作

                             

int InsertQueue(LinkQ *q,Elemtype e){
    Qlinklist p=(Qlinklist)malloc(sizeof(Qnode));
	if(p=NULL){
		exit(0);
	} 	
	p->data=e;
	p->next=NULL;//等会新节点要插在尾结点之后,用来充当新的尾结点 ,所以指针指向空 
	//队列的插入操作是在尾部进行的 
	q->rear->next=p;
	q->rear=p;
}

                              D:删除操作

队列中节点数>1时

                                         

链表中只有一个节点时

 

int DeleteQueue(LinkQ *q,Elemtype &e){
	Qlinklist p;
	if(q->front==q->rear)//队列空
	{
	  return -1;	
	} 
	//先用p保存当前第一个节点即需出列的队头,用e返回其数据 
	p=q->front->next;
	*e=p->data;
	//真正的删除开始啦
	 q->front->next=p->next;
	 if(q->rear==p){
	 //这是队列只有一个节点的情况
	 q->rear=q->front; //出列后队空,所以要首尾合一 
	 }
	 free(p);
} 

                                     E:销毁队列

                        //由于链队列建立在内存的动态区,因此当队列不在有用时应及时销毁,以免过多占用内存空间

int DestroyQueue(LinkQ *q){
	while(q->front){
		q->rear=q->front->next;//尾指针直接与头指针汇合,相当于删除中间节点 
		free(q->front);//删除头结点 
		q->front=q->rear;//表空,首尾合一 
	}
} 

                            F:完整测试程序(AC)

#include<stdio.h>
#include<malloc.h>
#define Elemtype int 
typedef struct Qnode{
	Elemtype data;
	struct Qnode *next;
}Qnode,*Qlinklist; 

typedef struct{
	Qlinklist front,rear;//定义队列的头指针front尾指针rear 
}LinkQ;

void initQueue(LinkQ *Q){
	Q->front=(Qlinklist)malloc(sizeof(Qnode));
	Q->rear=Q->front;
	Q->front->next=NULL; 
} 
int InsertQueue(LinkQ *Q,Elemtype e){
    Qlinklist p=(Qlinklist)malloc(sizeof(Qnode));
	if(p==NULL){
		return -1;
	} 	
	p->data=e;
	p->next=NULL;//等会新节点要插在尾结点之后,用来充当新的尾结点 ,所以指针指向空 
	//队列的插入操作是在尾部进行的 
	Q->rear->next=p;
	Q->rear=p;
	return 0;
}
int DeleteQueue(LinkQ *Q,Elemtype &e){
	Qlinklist p;
	if(Q->front==Q->rear)//队列空
	{
	  return -1;	
	} 
	//先用p保存当前第一个节点即需出列的队头,用e返回其数据 
	p=Q->front->next;
	e=p->data;
	//真正的删除开始啦
	 Q->front->next=p->next;
	 if(Q->rear==p){
	 //这是队列只有一个节点的情况
	 Q->rear=Q->front; //出列后队空,所以要首尾合一 
	 }
	 free(p);
	 return 1;
} 
//由于链队列建立在内存的动态区,因此当队列不在有用时应及时销毁,以免过多占用内存空间
int DestroyQueue(LinkQ *Q){
	while(Q->front){
		Q->rear=Q->front->next;//尾指针直接与头指针汇合,相当于删除中间节点 
		free(Q->front);//删除头结点 
		Q->front=Q->rear;//表空,首尾合一 
	}
	return 1;
} 
//遍历并计算队列长度 
void visit(LinkQ *Q){
	Qlinklist p;
	int i=0;
	p=Q->front->next;
	while(p!=NULL){
		printf("%d ",p->data);
	     i++;
		p=p->next;		
	}
	printf("队列中有%d个元素\n",i);
} 
int main(){
	LinkQ Q;int n,i,a[100],e;
	printf("你想建立多长的队列?\n");
    initQueue(&Q);
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
		InsertQueue(&Q,a[i]);
	}
	visit(&Q);
    DeleteQueue(&Q,e);
    printf("出列节点数据为%d\n",e);
    visit(&Q);
    DestroyQueue(&Q);
 	return 0;
 }


 

第三种:循环队列

                                             ----->https://blog.csdn.net/qq_38193883/article/details/97792298

  • 又到了正经致谢的神圣时刻!哈哈哈哈哈啊哈哈~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值