数据结构学习(七)——链队列的操作

队列的存储方式除了有顺序队列,还可以有链队列这种形式。链队列是采用链式结构存储的队列,类似单链表,但操作受限制,只允许在表头删除结点和在表尾插入结点。

在链队列中,除了有一个头指针外,还要有一个尾指针。在队头还需要加一个头结点,当队列为空时,头指针与尾指针同时指向头结点。为了与头结点区分开,称队列的第一个结点(头结点后面的第一个结点)为队头结点。

下面的代码就是对链队列的一些操作,其中有个问题还让我纠结了会儿。

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

typedef struct list
{
	char data;
	struct list *next;
}linklist;

typedef struct node
{
	linklist *front;					
	linklist *rear;
}linksequeue;	//链队列

linksequeue *Linksequeue_CreateEnd();				//尾插法创建链队列
char Linksequeue_GetFront(linksequeue *q);			//取得头结点
void Linksequeue_In(linksequeue *q, char dat);		//入队
char Linksequeue_Out(linksequeue *q);				//出队
void ShowLinksequeue(linksequeue *q);				//输出显示队列

int main(void)
{
	linksequeue *q;
	int choice;
	char ch, ans;

	printf("链队列的操作练习:\n");
	printf("依次输入队列结点数据('#'号表示结束):\n");
	q = Linksequeue_CreateEnd();
	getchar();

	while(1)
	{
		printf("链队列操作:\n");
		printf("1.取头结点\n");
		printf("2.入队\n");
		printf("3.出队\n");
		printf("4.输出显示队列\n");
		printf("5.退出程序\n");
		printf("做出选择:\n");
		scanf("%d", &choice);
		getchar();					//消除回车键带来的影响

		switch(choice)
		{
		//取头结点
		case 1:
			ch = Linksequeue_GetFront(q);
			if(ch)
				printf("头结点为%c\n",ch);
			else
				printf("取头结点失败!\n");
			break;
		//入队
		case 2:
			printf("输入想入队的字符数据:");
			scanf("%c", &ch);
			Linksequeue_In(q, ch);
			break;
		//出队
		case 3:
			ans = Linksequeue_Out(q);
			if(ans != '\0')
			{
				printf("出队成功!\n");
				printf("出队数据为%c\n", ans);
			}
			else
				printf("出队失败!\n");
			break;
		//输出显示队列
		case 4:
			ShowLinksequeue(q);
			break;
		//退出程序
		case 5:
			return 0;
			break;
		default:
			printf("选择无效!\n");
			break;
		}
	}
	return 1;

}

//链队列置空
void Linksequeue_SetNull(linksequeue *q)
{
	q->front = (linklist*)malloc(sizeof(linklist));
	q->front->next = NULL;		//队头结点为空,尾结点指向头结点
	q->rear = q->front;
}

//判断链队列是否为空
int Linksequeue_Empty(linksequeue *q)
{
	if(q->front == q->rear)		//头结点等于尾结点则为空
		return 1;
	else
		return 0;
}

//创建链队列
linksequeue *Linksequeue_CreateEnd()
{
	linksequeue *q;
	char ch;
 
	q = (linksequeue*)malloc(sizeof(linksequeue));		//关键啊!!!开始忘了,程序始终有问题- -!!
	Linksequeue_SetNull(q);
	ch = getchar();

	while(ch != '#')
	{
		Linksequeue_In(q, ch);			//入队
		ch = getchar();
	}
	return q;
}

//取得头结点
char Linksequeue_GetFront(linksequeue *q)
{
	if(Linksequeue_Empty(q))		//先判断链队列是否为空
		return '\0';
	else
		return q->front->next->data;
}

//入队
void Linksequeue_In(linksequeue *q, char dat)
{
	q->rear->next = (linklist*)malloc(sizeof(linklist));	
	q->rear = q->rear->next;		//尾结点移动
	q->rear->data = dat;			
	q->rear->next = NULL;			//尾结点为空
}

//出队
char Linksequeue_Out(linksequeue *q)
{
	linklist *s;

	if(Linksequeue_Empty(q))			//先要判断队列是否为空
		return 0;
	else
	{
		s = q->front;					//头结点移动到头结点的下一个节点
		q->front = s->next;
		free(s);
		return q->front->data;
	}
}

//输出显示队列
void ShowLinksequeue(linksequeue *q)
{
	linklist *s;
	
	s = q->front->next;
	while(s != NULL)
	{
		putchar(s->data);
		putchar(' ');
		s = s->next;
	}
	printf("\n");
}

其中让我纠结的就是创建链队列中的一句关于空间申请的语句q = (linksequeue*)malloc(sizeof(linksequeue));开始没有这条语句时,程序就不执行while(1)里面的语句了。运行程序输入一串字符后,提示命令结束。开始百思不得其解,不知道为什么,后来灵感莫名以来,感觉是没有申请空间的问题,然后加上这条语句后果然正确。至于其中真正原因,目前还不知道,有知道的高手如果看见这片文章的话,望解答我的疑惑。让我知其所以然。

你可能感兴趣的:(数据结构学习(七)——链队列的操作)