棧(Stack)和佇列(Queue)
- 什麼是棧(棧儲存結構)
- 順序棧及基本操作(包含入棧和出棧)
- 什麼是佇列(佇列儲存結構)
- 鏈式佇列及基本操作(C語言實現)
- 用C語言實現棧及各個功能(陣列)
- 用C語言實現佇列及各個功能(連結串列)
- 棧和佇列的主要區別
1.什麼是棧(棧儲存結構)
同順序表和連結串列一樣,棧也是用來儲存邏輯關係為 "一對一" 資料的線性儲存結構
佇列儲存結構的實現有以下兩種方式:
基於棧結構的特點,在實際應用中,通常只會對棧執行以下兩種操作:
- 向棧中新增元素,此過程被稱為"進棧"(入棧或壓棧);
- 從棧中提取出指定元素,此過程被稱為"出棧"(或彈棧);
棧特點:棧是一種只能從表的一端存取資料且遵循 "先進後出" 原則的線性儲存結構。
2.順序棧及基本操作(包含入棧和出棧)
順序棧,即用順序表實現棧儲存結構。使用棧儲存結構操作資料元素必須遵守 "先進後出" 的原則。
用棧儲存結構儲存{1,2,3,4}
,其儲存狀態如圖 所示:
入棧:1,2,3,4
出棧:4,3,2,1
3.什麼是佇列(佇列儲存結構)
佇列,和棧一樣,也是一種對資料的"存"和"取"有嚴格要求的線性儲存結構。
與棧結構不同的是,佇列的兩端都"開口",要求資料只能從一端進,從另一端出。
通常,稱進資料的一端為 "隊尾",出資料的一端為 "隊頭",資料元素進佇列的過程稱為 "入隊",出佇列的過程稱為 "出隊"。如圖所示:
佇列儲存結構的實現有以下兩種方式:
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. 棧:只能從頂部取資料,也就是說最先進入棧底的,需要遍歷整個棧才能取出來,而且在遍歷資料的同時需要為資料開闢臨時空間,保持資料在遍歷前的一致性。