1. 程式人生 > 其它 >棧(Stack)和佇列(Queue)

棧(Stack)和佇列(Queue)

技術標籤:C筆記c語言資料結構佇列

  1. 什麼是棧(棧儲存結構
  2. 順序棧及基本操作(包含入棧和出棧)
  3. 麼是佇列(佇列儲存結構)
  4. 鏈式佇列及基本操作(C語言實現)
  5. 用C語言實現棧及各個功能(陣列)
  6. 用C語言實現佇列及各個功能(連結串列)
  7. 棧和佇列的主要區別

1.什麼是棧(棧儲存結構

順序表連結串列一樣,棧也是用來儲存邏輯關係為 "一對一" 資料的線性儲存結構

佇列儲存結構的實現有以下兩種方式:

  1. 順序棧:在順序表的基礎上實現的棧結構;
  2. 鏈棧:在連結串列的基礎上實現的棧結構;

基於棧結構的特點,在實際應用中,通常只會對棧執行以下兩種操作:

  • 向棧中新增元素,此過程被稱為"進棧"(入棧或壓棧);
  • 從棧中提取出指定元素,此過程被稱為"出棧"(或彈棧);

棧特點:棧是一種只能從表的一端存取資料且遵循 "先進後出" 原則的線性儲存結構。


2.順序棧及基本操作(包含入棧和出棧)

順序,即用順序表實現棧儲存結構。使用棧儲存結構操作資料元素必須遵守 "先進後出" 的原則。

用棧儲存結構儲存{1,2,3,4},其儲存狀態如圖 所示:

入棧:1,2,3,4

出棧:4,3,2,1


3.什麼是佇列(佇列儲存結構)

佇列,和一樣,也是一種對資料的"存"和"取"有嚴格要求的線性儲存結構
與棧結構不同的是,佇列的兩端都"開口",要求資料只能從一端進,從另一端出。

通常,稱進資料的一端為 "隊尾",出資料的一端為 "隊頭",資料元素進佇列的過程稱為 "入隊",出佇列的過程稱為 "出隊"。如圖所示:

佇列儲存結構的實現有以下兩種方式:

  1. 順序佇列:在順序表的基礎上實現的佇列結構;
  2. 鏈佇列:在連結串列的基礎上實現的佇列結構;

4.鏈式佇列及其操作

鏈式佇列,簡稱"鏈佇列",即使用連結串列實現的佇列儲存結構。

需建立兩個指標(命名為 top 和 rear)分別指向連結串列中佇列的隊頭元素和隊尾元素,如圖所示:

入列如圖所示·:

入列:1,2,3,4

出列:1,2,3,4


4.用C語言實現棧及各個功能(陣列)

//動態棧(陣列)(可動態增容)
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int  top;//棧頂下標
	int  capacity;
}Stack;
//棧的初始化
void StackInit(Stack* ps)
{
	ps->a = malloc(sizeof(STDataType) * 4);
	ps->top = 0;
	ps->capacity = 4;
}
//入棧
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	ps->a[ps->top] = data;
	ps->top++;
	if (ps->top == ps->capacity) {
		ps->capacity *= 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity);
		if (tmp == NULL) {
			printf("Apply error!");
			exit(-1);
		}
		else
			ps->a = tmp;
	}
}
// 出棧 
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}
//獲取棧中個數
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->top;
}

// 銷燬棧 
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}
// 檢測棧是否為空,如果為空返回非零結果,如果不為空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	if (ps->top == 0)
		return 1;
	else
		return 0;
}
// 獲取棧頂元素 
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->a[ps->top - 1];
}

6.用C語言實現佇列及各個功能(連結串列)

//佇列的連結串列結構
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QueueNode;
typedef struct Queue
{
	QueueNode* head;
	QueueNode* tail;
}Queue;
//初始化佇列
void QueueInit(Queue* ps)
{
	assert(ps);
	ps->head =ps->tail = NULL;
}
//銷燬佇列
void QueueDestroy(Queue* ps)
{
	QueueNode* cur = ps->head;
	while (cur) {
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	ps->head = ps->tail = NULL;
}
// 隊尾入佇列 
void QueuePush(Queue* ps, QDataType data)
{
	QueueNode* NewNode = (QueueNode*)malloc(sizeof(QueueNode));
	if (NewNode == NULL) {
		printf("apply erroe!");
		exit(-1);
	}
	else
		NewNode->data = data;
	    NewNode->next = NULL;
	if (ps->head == NULL) {
			ps->head = ps->tail = NewNode;
	 }
	else {
		ps->tail->next = NewNode;
		ps->tail = NewNode;
	}

}
// 隊頭出佇列
void QueuePop(Queue* ps)
{
	assert(ps);
	assert(ps->head);
	QueueNode* next = ps->head->next;
	free(ps->head);
	ps->head = next;
	if (ps->head == NULL) {
		ps->tail = NULL;
	}
}
// 獲取佇列頭部元素 
QDataType QueueFront(Queue* ps)
{
	assert(ps);
	assert(ps->head);
	return ps->head->data;
}
// 獲取佇列隊尾元素 
QDataType QueueBack(Queue* ps)
{
	assert(ps);
	assert(ps->head);
	return ps->tail->data;
}
// 檢測佇列是否為空,如果為空返回非零結果,如果非空返回0
int QueueEmpty(Queue* ps)
{
	assert(ps);
	if (ps->head == NULL)
		return 1;
	else
		return 0;
}
// 獲取佇列中有效元素個數
int QueueSize(Queue* ps)
{
	assert(ps);
	QueueNode* cur = ps->head;
	QDataType size = 0;
	while (cur) {
		size++;
		cur = cur->next;
	}
	return size;
}

7.棧和佇列的主要區別

佇列(Queue):是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表;
棧(Stack):是限定只能在表的一端進行插入和刪除操作的線性表。
一、規則不同
1. 佇列:先進先出(First In First Out)FIFO
2. 棧:先進後出(First In Last Out )FILO
二、對插入和刪除操作的限定不同
1. 佇列:只能在表的一端進行插入,並在表的另一端進行刪除;
2. 棧:只能在表的一端插入和刪除。
三、遍歷資料速度不同
1. 佇列:基於地址指標進行遍歷,而且可以從頭部或者尾部進行遍歷,但不能同時遍歷,無需開闢空間,因為在遍歷的過程中不影響資料結構,所以遍歷速度要快;
2. 棧:只能從頂部取資料,也就是說最先進入棧底的,需要遍歷整個棧才能取出來,而且在遍歷資料的同時需要為資料開闢臨時空間,保持資料在遍歷前的一致性。