链式队列的基本操作

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//链式队列的构造,遍历等基本操作

/*
 问题:
                        1.初始化无法运行,下一步没有进行
                        2.加上初始化以后仅仅输入一次程序就崩溃了,进行调试查找,在入队
                            p->next=s之类的语句附近停止,并弹出CPU窗口,附图


                        3.在构造栈的过程中也遇到此类问题,后查询百度,借鉴他人的代码,进行了更改
                        地址如下:
                       https://blog.csdn.net/ibelievesunshine/article/details/80048461

解决:
                        1.经过查询和百度,发现需要前置和后置lq指针需进行内存分配,这一点书上没有提到
                        2.经过借鉴将lq的内存分配移到了case1中,并且初始化函数放在了内存分配之后,才可以运行
                            这一点令我很费解
                             2.1经过思考,感觉应该是如果不分配内存,则无法存储数据,因为没有相应的空间,类似于构
                                  成队列的结点

                             后来经过询问,老师意思是语法没问题,正常可以运行,但因为编译器和选择的语言不同,所以

                             可能需要分配内存。
                             2.2 两个初始化方式,第一个直接接在头节点,第二个方式来自于
                                https://blog.csdn.net/HZPHYT/article/details/81430940
                                第二个方式使用后如果想要遍历和出队,需要使指针指向lq->front->next
                                否则会多处front中data的值

附图代码:

结构体:

typedef struct QNode                //定义队列结构体 
{
	int data;
	struct QNode *next;
}QType;

typedef struct qptr                 //定义队列前置节点和后置结点结构体 
{
	QType *front,*rear;
}LinkQueue; 

初始化,两个方法:

个人建议这个方法,方便一些

//前置后置结点初始化

//方式一 

void InitQueue(LinkQueue *lq)  		 
{	
	lq->front=NULL;                 //令前置和后置结点都为空 
	lq->rear=NULL;
}

方法二

//此方法初始化front自带空间,因此遍历和输出时需指向lq->front->next,才能从第一个开始输出

//初始化方式二
void InitQueue(LinkQueue *lq)
{
	lq->front=lq->rear=(QType*)malloc(sizeof(QType));     
	//此方法初始化front自带空间,因此遍历和输出时需指向lq->front->next,才能从第一个开始输出 
} 

入队操作:

void EnQueue(LinkQueue *lq,int x)
{
	QType *p;
	p=(QType*)malloc(sizeof(QType));      //分配内存 
	p->data=x;
	p->next=NULL;
	if(lq->front==NULL&&lq->rear==NULL)   //若第一次入队,则令前置后置指针指向元素 
	{
		lq->front=lq->rear=p;
	}
	else                                  //若不是第一次入队,则rear指针后移 
	{
		lq->rear->next=p;
		lq->rear=p;	
	}
} 

遍历队列元素

方便观察是否建立成功

同时需要注意,如果使用第二种初始化方法,则

if判断空栈条件为lq->front==lq->rear,while判断是否可以输出,判断应为p!=lq->rear->next,让p指向头节点时,应为p=lq->dront->next

//遍历队列元素 
int ShowQueue(LinkQueue *lq)
{
	QType *p;
	p=(QType*)malloc(sizeof(QType));
	//判断是否为空栈 
	if(lq->front==NULL&&lq->rear==NULL)            //若选择方法二初始化,则空栈条件为lq->front==lq->rear 
	{
		printf("为空栈\n");
		return 0;
	}
	//令指针指向头节点 
	p=lq->front;									//若选择方法二,则应为p=lq->front->next
	//输出队列元素								    
	while(p!=NULL)                                 
	{
		printf("%d\n",p->data);
		p=p->next;									//若选择方法二作为是否输出元素标准,则判断应为p!=lq->rear->next 
	}
	return 0;
	
	
}

出队函数

//出队函数 
int DeQueue(LinkQueue *lq,int x)
{
	int i;
	QType *p,*q;	
	for(i=0;i<x;i++)
	{
		p=lq->front;
		printf("出队元素为:%d\n",p->data);
		lq->front=p->next;
		free(p);
	}
	return 0; 
}

计算队列长度,以防出队时冒出

//计算队列长度 
int LenQueue(LinkQueue *lq,int x)
{
	QType *p;
	int num=0;
	p=lq->front;
	while(p!=NULL)                           //判断是否到对尾,如果没到则计数器加一,指针后移 
	{
		num++;
		p=p->next;
	}
	if(num>x)							     //如果出队数大于队列中元素总数,则返回0,反之返回1 
		return 1;
	else
		return 0;
}

附图全部代码

#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

typedef struct QNode                //定义队列结构体 
{
	int data;
	struct QNode *next;
}QType;

typedef struct qptr                 //定义队列前置节点和后置结点结构体 
{
	QType *front,*rear;
}LinkQueue; 

//前置后置结点初始化

//方式一 

void InitQueue(LinkQueue *lq)  		 
{	
	lq->front=NULL;                 //令前置和后置结点都为空 
	lq->rear=NULL;
}
/*
//初始化方式二
void InitQueue(LinkQueue *lq)
{
	lq->front=lq->rear=(QType*)malloc(sizeof(QType));     
//此方法初始化front自带空间,因此遍历和输出时需指向lq->front->next,才能从第一个开始输出 
} 
*/


//入队操作 
 
void EnQueue(LinkQueue *lq,int x)
{
	QType *p;
	p=(QType*)malloc(sizeof(QType));      //分配内存 
	p->data=x;
	p->next=NULL;
	if(lq->front==NULL&&lq->rear==NULL)   //若第一次入队,则令前置后置指针指向元素 
	{
		lq->front=lq->rear=p;
	}
	else                                  //若不是第一次入队,则rear指针后移 
	{
		lq->rear->next=p;
		lq->rear=p;	
	}
} 


//遍历队列元素 
int ShowQueue(LinkQueue *lq)
{
	QType *p;
	p=(QType*)malloc(sizeof(QType));
	//判断是否为空栈 
	if(lq->front==NULL&&lq->rear==NULL) //若选择方法二初始化,则空栈条件为lq->front==lq->rear 
	{
		printf("为空栈\n");
		return 0;
	}
	//令指针指向头节点 
	p=lq->front;									//若选择方法二,则应为p=lq->front->next
	//输出队列元素								    
	while(p!=NULL)                                 
	{
		printf("%d\n",p->data);
		p=p->next;									//若选择方法二作为是否输出元素标准,则判断应为p!=lq->rear->next 
	}
	return 0;
	
	
}

//出队函数 
int DeQueue(LinkQueue *lq,int x)
{
	int i;
	QType *p,*q;	
	for(i=0;i<x;i++)
	{
		p=lq->front;
		printf("出队元素为:%d\n",p->data);
		lq->front=p->next;
		free(p);
	}
	return 0; 
}

//计算队列长度 
int LenQueue(LinkQueue *lq,int x)
{
	QType *p;
	int num=0;
	p=lq->front;
	while(p!=NULL)                           //判断是否到对尾,如果没到则计数器加一,指针后移 
	{
		num++;
		p=p->next;
	}
	if(num>x)							     //如果出队数大于队列中元素总数,则返回0,反之返回1 
		return 1;
	else
		return 0;
}

int main() 
{
	LinkQueue *lq;
	int x=0,sel,j;
	
	do
    {
		printf("------------------------------\n");
    	printf("    1   创建队列(必须进行)    \n");
    	printf("    2   入队操作    \n");
    	printf("    3   出队操作    \n");
    	printf("    4   显示队列中的元素    \n");
    	printf("    5   退出  \n");
    	printf("------------------------------\n");
    	printf("请选择(1,2,3,4,5):");
    	scanf("%d",&sel);
    
    	switch(sel)
    	{
    		case 1:              //节点初始化
				lq=(LinkQueue*)malloc(sizeof(LinkQueue));            //为lq指针分配内存,并且初始化需要在后面
				InitQueue(lq);										//若不分配内存,则无法存储数据
				break; 										  
			case 2:
				printf("请输入入队数字:(-1停止)");
				scanf("%d",&x);
				while(x!=-1)
				{
					EnQueue(lq,x);				//入队
					scanf("%d",&x);
				}
				break;
			case 3:
				printf("请输入出队元素个数");         
				scanf("%d",&x);
				j=LenQueue(lq,x);                     //计算队列长度,并判断是否超出长度
				if(j==0)
				{
					printf("出队元素大于队列本身元素,无法出队\n"); 
					break;
				}
				DeQueue(lq,x);						   //出队函数
				break;
			case 4:
				ShowQueue(lq);						//遍历队列函数 
				break;
			case 5:return 0; 						//退出 
				
				 
			 
		}
    	
    	
	}
	while(1);	
	return 0;
} 

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值