数据结构(五)——队列

相对于栈,队列(queue)是另外一种特殊的线性表。队列的逻辑设计是,删除运算限定在表的一端进行,插入运算则被限定在表的另一端进行。约定将允许插入的一端称为队尾(Rear),删除的那一端称为队首(Front)。这样的逻辑设计,就其实是现实生活里的排队嘛。因此,队列是先进先出表(First In Frist Out,FIFO)。

队列同样有顺式结构和链式结构(一种逻辑结构的两种物理结构)。顺式的长度必然受到限制,所以主要都是使用链式结构。队列的链式结构本质上是用·一个单链表来表示。但是,同上一节的,栈一样。因为top/front这一端是一直被取出来的,和链表的head地址不能变有冲突,所以top/front这一端其实一直都是设置在链表的第二个结点。

队列的分类或者注意点:

  • 有(无)优先级队列

队列还分有,无优先级和有优先级(priority)两种。有优先级的,称为优先队列。优先队列的区别是:对每个进队的元素都规定有一个优先级,同时将队列分为若干个有各自优先级的子队列。当执行插入操作时,元素进入相应的优先级的子队列的队尾,而删除则是从优先级最高的一个子队列开始。

  • 顺序队列的bug和弥补

对于顺序队列,因为设计的问题可能有bug:一开始front和rear是同一个地址嘛。进队rear后移(地址增大),出队front也后移(地址增大),那么划分的这一片物理区间,前面的地区其实就会因为front后移而变空了,,导致“虚溢出”。
对此,提出的两种解决方法是,
——平移元素,即是当一个元素出队时,将整个队列的元素都向前移动一个位置。但是效率太低,不适宜。
——将整个队列设计为循环队列(在物理结构上),这样子就可以处理了。不过要设置变量之类,判断到底是队列空了,还是队列满了(因为这个时候,rear的地址会等于front地址)。

以下提供的是自己的链式队列程序:
(其实理解了队列的逻辑结构后,写程序是很简单的)
链式队列的结构体:

typedef int elementype;
typedef struct node{
	elementype data;
	struct node * next;
}node;
typedef struct queuechain{
	node * front;
	node * rear;
	elementype length;
} queuechain;

各个操作函数:

void insertNode(queuechain * QueueChain,elementype DatatoRear);
void getNode(queuechain * QueueChain,elementype * DatafromFront);
void printNode(queuechain * QueueChain);
void destroyQueueChain(queuechain * QueueChain);

进队函数:

void insertNode(queuechain * QueueChain,elementype DatatoRear)
{
	node * tempnode = (node *)malloc(sizeof(node));
	if(!tempnode){
		printf("init node is falsed\n");
		return;
	}
	tempnode->data = DatatoRear;
	tempnode->next = NULL;
	
	QueueChain->rear->next = tempnode;
	QueueChain->rear = tempnode;
	QueueChain->length++;
	
	printf("insert %d to the rear\n",tempnode->data);
}

出队函数:

void getNode(queuechain * QueueChain,elementype * DatafromFront)
{
	node * tempnode;
	
	if(QueueChain->front == QueueChain->rear){
		printf("the QueueChain is empty\n");
	}
	
	//由于链表的本身性质,头结点是不可能被删除,也就不能被作为真正意义上的front了
	tempnode = QueueChain->front->next; 
	*DatafromFront = tempnode->data;
	QueueChain->front->next = tempnode->next;

	QueueChain->length--;
	printf("get %d from the front\n",tempnode->data);
	free(tempnode); 
}

print函数

void printNode(queuechain * QueueChain)
{
	node * tempnode;
	int i = 1;
	tempnode = QueueChain->front->next; 
	if(tempnode == NULL){
		printf("the queuechain is empty\n");
		return ;
	}
	while(tempnode->next != NULL){
		printf("the data of the %d is %d\n",i++,tempnode->data);
		tempnode = tempnode->next;
	}
	printf("the data of the %d is %d\n",i++,tempnode->data);
}

destroy函数:

void destroyQueueChain(queuechain * QueueChain)
{
	while(QueueChain->front->next != NULL){
		QueueChain->rear = QueueChain->front->next;
		free(QueueChain->front);
		QueueChain->front = QueueChain->rear;
	}
	//其实front这个还没有free,就是说,只剩下front这个点,才能给print函数,做一个判断 
	//free(QueueChain->front);
	printf("destroy is finished\n");
}

全部程序:

#include<stdio.h>
#include<malloc.h>

/*****

功能设计、分part:
还是按照之前的,不做交互。
init那部分,在主函数那里做,不然总觉得有bug
(insert和get其实就已经是不止是读了,还是取出来的了) 
先做的,init——insert——get—— print——length——clear 

*****/
typedef int elementype;
typedef struct node{
	elementype data;
	struct node * next;
}node;
typedef struct queuechain{
	node * front;
	node * rear;
	elementype length;
} queuechain;

void insertNode(queuechain * QueueChain,elementype DatatoRear);
void getNode(queuechain * QueueChain,elementype * DatafromFront);
void printNode(queuechain * QueueChain);
void destroyQueueChain(queuechain * QueueChain);


int main()
{
	int DatafromFront = 0;
	queuechain * QueueChain = (queuechain *)malloc(sizeof(queuechain));
	if(QueueChain == NULL){
		printf("init the queuechain is false\n");
		return 0;
	}
	printf("init the queuechain is succeed\n");
	
	QueueChain->front = (node *)malloc(sizeof(node));
	if(QueueChain->front == NULL){
		printf("init the queuechain front is false\n");
		return 0;
	}
	printf("init the queuechain front is succeed\n");
	
	QueueChain->rear = QueueChain->front;
	QueueChain->length = 0;
	QueueChain->front->next = NULL; 
	
	QueueChain->rear->data = 33;
	
	insertNode(QueueChain, 23);
	insertNode(QueueChain, 24);
	insertNode(QueueChain, 25);
	
	printNode(QueueChain); 
	
	
	
	getNode(QueueChain,&DatafromFront);
	
	destroyQueueChain(QueueChain);
	printNode(QueueChain); 
	
	return 0;
	
} 

void insertNode(queuechain * QueueChain,elementype DatatoRear)
{
	node * tempnode = (node *)malloc(sizeof(node));
	if(!tempnode){
		printf("init node is falsed\n");
		return;
	}
	tempnode->data = DatatoRear;
	tempnode->next = NULL;
	
	QueueChain->rear->next = tempnode;
	QueueChain->rear = tempnode;
	QueueChain->length++;
	
	printf("insert %d to the rear\n",tempnode->data);
}

void getNode(queuechain * QueueChain,elementype * DatafromFront)
{
	node * tempnode;
	
	if(QueueChain->front == QueueChain->rear){
		printf("the QueueChain is empty\n");
	}
	
	//由于链表的本身性质,头结点是不可能被删除,也就不能被作为真正意义上的front了
	tempnode = QueueChain->front->next; 
	*DatafromFront = tempnode->data;
	QueueChain->front->next = tempnode->next;

	QueueChain->length--;
	printf("get %d from the front\n",tempnode->data);
	free(tempnode); 
	

}


void printNode(queuechain * QueueChain)
{
	node * tempnode;
	int i = 1;
	tempnode = QueueChain->front->next; 
	if(tempnode == NULL){
		printf("the queuechain is empty\n");
		return ;
	}
	while(tempnode->next != NULL){
		printf("the data of the %d is %d\n",i++,tempnode->data);
		tempnode = tempnode->next;
	}
	printf("the data of the %d is %d\n",i++,tempnode->data);
}

void destroyQueueChain(queuechain * QueueChain)
{
	while(QueueChain->front->next != NULL){
		QueueChain->rear = QueueChain->front->next;
		free(QueueChain->front);
		QueueChain->front = QueueChain->rear;
	}
	//其实front这个还没有free,就是说,只剩下front这个点,才能给print函数,做一个判断 
	//free(QueueChain->front);
	printf("destroy is finished\n");

}

附图·:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38181811/article/details/88549057