/* 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;
}