1. 程式人生 > >《資料結構》嚴蔚敏 鏈式儲存實現佇列 演算法3_4_2

《資料結構》嚴蔚敏 鏈式儲存實現佇列 演算法3_4_2

這個用連結串列代替陣列來實現佇列
這個程式碼書寫的時候注意ClearQueue(Link_Queue *q)DestroyQueue(Link_Queue *q)這兩個函式

前者在寫的時候:要注意第一步是先將rear指標挪到指向佇列首元素的位置,然後一舉將剩下的元素一併釋放,接著再釋放首元素,然後使兩個指標都指向頭節點

後者在寫的時候:要注意第一步也是先將rear指標挪到指向佇列首元素的位置,但是此時是將包括首元素在內一併都釋放掉。然後讓兩個指標都指向空。

剩下的和連結串列操作就差不多了,無需多費口舌
在這裡插入圖片描述

//用鏈式儲存佇列
//注意ClearQueue(Link_Queue *q) 寫得很全面
#include<stdio.h>
#include<stdlib.h>

#define OK 0
#define ERROR -1


typedef int Status;
typedef int QElemType;


//連結串列上鍊的每一個結構
typedef struct QNode
{
	QElemType data;
	struct QNode *next;
	
}QNode,*QueuePtr;

//連結串列本身

typedef struct
{
	QueuePtr front;
	QueuePtr rear;
}Link_Queue;

Status
InitQueue(Link_Queue * q)
{
	//建立一個頭節點和一個頭指標

	q->front = (QueuePtr)malloc(sizeof(QNode));
	if(q->front == NULL)
		//return ERROR;
		exit(ERROR);
	
	q->rear = q->front;
	q->front->next = NULL;

	return OK;	

}

Status
DestroyQueue(Link_Queue *q)
{
	//free(q);
	//這考慮的也太navie了

	while(q->front)
	{
		q->rear = q->front->next;
		free(q->front);
		q->front = q->rear;
	}
	return OK;
}

//巧妙

Status
ClearQueue(Link_Queue *q)
{
	// if(q->front != q->rear)
	// 	q->front --;
	// q->front->next = NULL;

	q->rear = q->front->next;//先儲存一下
	while(q->rear)
	{
		q->front->next = q->rear->next;
		free(q->rear);
		q->rear = q->front->next;
	}

	q->rear = q->front;

	return OK;
}

Status
QueueEmpty(Link_Queue q)
{
	if(q.front == q.rear)
		return OK;
	else
		return ERROR;

}

int
QueueLength(Link_Queue q)
{
	int count = 0;
	QueuePtr p = q.front;
	while(p != q.rear)
	{
		count++;
		p=p->next;
	}

	return count;
	//return q.rear - q.front;
	//this have a little question
	//算不算上頭節點呢,是用頭減尾還是尾減頭呢?

}

Status
GetHead(Link_Queue q,QElemType *e)
{
	*e = q.front->next->data;

	return OK;

}

Status
EnQueue(Link_Queue *q,QElemType e)
{
	QueuePtr temp;
	temp = (QueuePtr)malloc(sizeof(QNode));
	if(temp == NULL)
		//return ERROR;
		exit(ERROR);

	temp->data = e;
	//temp = q->front;
	// while( temp != q->rear) //這裡有尾指標啊大哥
	// {
	// 	temp = temp->next;
	// }

	//q->rear->next = temp;
	temp->next = NULL;

	q->rear->next = temp;
	q->rear = temp;
	//最後要把為指標改變一下

	return OK;


}

Status
DeQueue(Link_Queue *q,QElemType *e)
{
	if( q->front == q->rear ) return ERROR;
	//刪除的時候要把原來的儲存一下,好釋放空間

	QueuePtr temp;
	temp = q->front->next;
	*e = temp->data;
	q->front->next = temp->next;

	//當刪除最後一個元素時需要注意⚠️此時隊尾指標丟了
	if(q->rear == temp)
		q->rear = q->front;

	free(temp); 

	//q->front->next = q->front->next->next;

	return OK;
	
}

Status
QueueTraverse(Link_Queue q,void(*visit)(QElemType ))
{
	if( q.front == q.rear ) return ERROR;
	while(q.front != q.rear)
	{
		q.front = q.front->next;
		visit(q.front->data);	
	}

	printf("\n");

	return OK;
}

void
visit(QElemType c)
{
	printf("%d ", c);
}

int main(int argc, char const *argv[])
{
	Link_Queue q;
	QElemType delete,length;
	InitQueue(&q);

	EnQueue(&q,1);
	EnQueue(&q,2);
	EnQueue(&q,3);
	EnQueue(&q,4);

	GetHead(q,&delete);
	printf("top is %d ", delete);
	printf("\nAfter insert: ");
	QueueTraverse(q,visit);

	length = QueueLength(q);

	printf("queue length is %d \n", length);

	DeQueue(&q,&delete);

	printf("\ndelete %d is ok!\n", delete);
	printf("\nAfter delete: ");

	QueueTraverse(q,visit);

	length = QueueLength(q);

	printf("queue length is %d \n", length);

	printf("\n");


	return 0;
}