栈和队列基本操作
棧和隊列
- 一、棧
- 棧是什么
- 棧的實現
- 棧的基本操作
- 棧類型的定義
- 初始化棧
- 檢查棧是否為滿
- 入棧
- 出棧
- 獲取棧頂元素
- 檢測棧是否為空
- 測試函數
- 完整代碼
- Stack.h
- Stack.c
- main.c
- 二、隊列
- 隊列是什么
- 隊列的實現
- 隊列類型的定義
- 申請一個節點
- 初始化隊列
- 隊尾入隊列
- 隊頭出隊列
- 獲取隊列頭部元素
- 獲取隊列隊尾元素
- 獲取隊列中有效元素個數
- 檢測隊列是否為空
- 銷毀隊列
- 測試函數
- 完整代碼
- Queue.h
- Queue.c
- main.c
- 三、環形隊列
- 假溢出問題
一、棧
棧是什么
??棧:一種特殊的線性表,其只允許在固定的一端進行插入和刪除元素操作。進行數據插入和刪除操作的一端稱為棧頂,另一端稱為棧底。棧中的數據元素遵守后進先出LIFO(Last In First Out)的原則。
壓棧:棧的插入操作叫做進棧/壓棧/入棧,入數據在棧頂。
出棧:棧的刪除操作叫做出棧。出數據也在棧頂。
棧遵循先進后出原則
棧的實現
??棧的實現一般可以使用數組或者鏈表實現,相對而言數組的結構實現更優一些。因為數組在尾上插入數據的代價比較小。
棧的基本操作
棧類型的定義
typedef int STDataType; typedef struct Stack {STDataType* a;int top; // 棧頂int capacity; // 容量 int size;}Stack;初始化棧
void StackInit(Stack* ps) {assert(ps);ps->a=(STDataType*)malloc(sizeof(STDataType)*5); if(NULL==ps->a){assert(0);return;}ps->capacity=5;ps->size=0; }檢查棧是否為滿
void CheckStack(Stack* ps) {assert(ps);if(ps->capacity==ps->size){//1.申請空間int newcapacity=ps->capacity*2;STDataType *temp=(STDataType*)malloc(sizeof(STDataType)*newcapacity);if(temp==NULL){assert(0);return;}//2.拷貝元素memcpy(temp,ps->a,sizeof(STDataType)*ps->size);//3.釋放舊空間free(ps->a);//4.使用新空間 ps->a=temp;ps->capacity=newcapacity;} }入棧
void StackPush(Stack* ps, STDataType data) {assert(ps);CheckStack(ps);ps->a[ps->size]=data;ps->size++; }出棧
void StackPop(Stack* ps) {assert(ps);if(!StackEmpty(ps)){ps->size--;}return; }獲取棧頂元素
STDataType StackTop(Stack* ps) {assert(ps);return ps->a[ps->size-1]; }// 獲取棧中有效元素個數 int StackSize(Stack* ps) {assert(ps);return ps->size; }檢測棧是否為空
int StackEmpty(Stack* ps) {assert(ps);return 0==ps->size; }// 銷毀棧 void StackDestroy(Stack* ps) {assert(ps);if(ps->a){free(ps->a);ps->a=NULL;ps->capacity=0;ps->size=0;} }測試函數
void TestStack() {Stack s;StackInit(&s);StackPush(&s,1);StackPush(&s,2);StackPush(&s,3);StackPush(&s,4);StackPush(&s,5);StackPush(&s,6);StackPush(&s,7);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackPop(&s);StackPop(&s);StackPop(&s);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackDestroy(&s); }完整代碼
Stack.h
typedef int STDataType; typedef struct Stack {STDataType* a;int top; // 棧頂int capacity; // 容量 int size;}Stack; // 初始化棧 void StackInit(Stack* ps); //檢查棧是否為慢void CheckStack(Stack* ps);// 入棧 void StackPush(Stack* ps, STDataType data); // 出棧 void StackPop(Stack* ps); // 獲取棧頂元素 STDataType StackTop(Stack* ps); // 獲取棧中有效元素個數 int StackSize(Stack* ps); // 檢測棧是否為空,如果為空返回非零結果,如果不為空返回0 int StackEmpty(Stack* ps); // 銷毀棧 void StackDestroy(Stack* ps);void TestStack();Stack.c
#include "Stack.h"#include<stdio.h> #include<malloc.h> #include<assert.h> #include<string.h>// 初始化棧 void StackInit(Stack* ps) {assert(ps);ps->a=(STDataType*)malloc(sizeof(STDataType)*5); if(NULL==ps->a){assert(0);return;}ps->capacity=5;ps->size=0; }// 檢查棧是否滿void CheckStack(Stack* ps) {assert(ps);if(ps->capacity==ps->size){//1.申請空間int newcapacity=ps->capacity*2;STDataType *temp=(STDataType*)malloc(sizeof(STDataType)*newcapacity);if(temp==NULL){assert(0);return;}//2.拷貝元素memcpy(temp,ps->a,sizeof(STDataType)*ps->size);//3.釋放舊空間free(ps->a);//4.使用新空間 ps->a=temp;ps->capacity=newcapacity;} }// 入棧 void StackPush(Stack* ps, STDataType data) {assert(ps);CheckStack(ps);ps->a[ps->size]=data;ps->size++; }// 出棧 void StackPop(Stack* ps) {assert(ps);if(!StackEmpty(ps)){ps->size--;}return; }// 獲取棧頂元素 STDataType StackTop(Stack* ps) {assert(ps);return ps->a[ps->size-1]; }// 獲取棧中有效元素個數 int StackSize(Stack* ps) {assert(ps);return ps->size; }// 檢測棧是否為空,如果為空返回非零結果,如果不為空返回0 int StackEmpty(Stack* ps) {assert(ps);return 0==ps->size; }// 銷毀棧 void StackDestroy(Stack* ps) {assert(ps);if(ps->a){free(ps->a);ps->a=NULL;ps->capacity=0;ps->size=0;} } void TestStack() {Stack s;StackInit(&s);StackPush(&s,1);StackPush(&s,2);StackPush(&s,3);StackPush(&s,4);StackPush(&s,5);StackPush(&s,6);StackPush(&s,7);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackPop(&s);StackPop(&s);StackPop(&s);printf("%d\n",StackTop(&s));printf("%d\n",StackSize(&s));StackDestroy(&s); }main.c
#include "Stack.h"int main() {TestStack();return 0; }二、隊列
隊列是什么
??隊列:只允許在一端進行插入數據操作,在另一端進行刪除數據操作的特殊線性表,隊列具有先進先出FIFO(First In First Out) 入隊列:進行插入操作的一端稱為隊尾 出隊列:進行刪除操作的一端稱為隊頭。
隊列的實現
??隊列也可以數組和鏈表的結構實現,使用鏈表的結構實現更優一些,因為如果使用數組的結構,出隊列在數組頭上出數據,效率會比較低。
隊列類型的定義
typedef int QDataType;typedef struct QNode { struct QNode* next; QDataType data; }QNode; // 隊列的結構 typedef struct Queue { QNode* front; QNode* rear; int size;}Queue;申請一個節點
QNode* buyQNode(QDataType data) {QNode *newnode=(QNode*)malloc(sizeof(QNode));if(NULL==newnode){assert(0);return NULL;}newnode->data=data;newnode->next=NULL;return newnode; }初始化隊列
void QueueInit(Queue* q) {assert(q);q->front=q->rear=NULL;q->size=0;}隊尾入隊列
void QueuePush(Queue* q, QDataType data) {assert(q);QNode *newnode=buyQNode(data);if(NULL==q->front){q->front=newnode; }else{q->rear->next=newnode; }q->rear=newnode;q->size++; }隊頭出隊列
void QueuePop(Queue* q) {assert(q);if(QueueEmpty(q)){return;}else{QNode *delndoe=q->front;q->front=delndoe->next;free(delndoe);if(NULL==q->front){q->rear=NULL;}}q->size--; }獲取隊列頭部元素
QDataType QueueFront(Queue* q) {assert(!QueueEmpty(q));return q->front->data; }獲取隊列隊尾元素
QDataType QueueBack(Queue* q) {assert(!QueueEmpty(q));return q->rear->data; }獲取隊列中有效元素個數
int QueueSize(Queue* q) {assert(!QueueEmpty(q));return q->size; }檢測隊列是否為空
int QueueEmpty(Queue* q) {assert(q);return NULL==q->front; }銷毀隊列
void QueueDestroy(Queue* q) {assert(q);QNode *cur=q->front;while(cur){q->front=cur->next;free(cur);cur=q->front;}q->rear=NULL;q->size=0; }測試函數
void TestQueue() {Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);if(QueueEmpty(&q)){printf("隊列已經為空\n");}else{printf("隊列不為空\n");}QueueDestroy(&q); }完整代碼
Queue.h
//鏈式結構:表示隊列 typedef int QDataType;typedef struct QNode { struct QNode* next; QDataType data; }QNode; // 隊列的結構 typedef struct Queue { QNode* front; QNode* rear; int size;}Queue; // 初始化隊列 void QueueInit(Queue* q); // 隊尾入隊列 void QueuePush(Queue* q, QDataType data); // 隊頭出隊列 void QueuePop(Queue* q); // 獲取隊列頭部元素 QDataType QueueFront(Queue* q); // 獲取隊列隊尾元素 QDataType QueueBack(Queue* q); // 獲取隊列中有效元素個數 int QueueSize(Queue* q); // 檢測隊列是否為空,如果為空返回非零結果,如果非空返回0 int QueueEmpty(Queue* q); // 銷毀隊列 void QueueDestroy(Queue* q);///void TestQueue();Queue.c
#include"Queue.h"#include<stdio.h> #include<assert.h> #include<malloc.h>//申請一個節點 QNode* buyQNode(QDataType data) {QNode *newnode=(QNode*)malloc(sizeof(QNode));if(NULL==newnode){assert(0);return NULL;}newnode->data=data;newnode->next=NULL;return newnode; }//初始化隊列 void QueueInit(Queue* q) {assert(q);q->front=q->rear=NULL;q->size=0;} // 隊尾入隊列 void QueuePush(Queue* q, QDataType data) {assert(q);QNode *newnode=buyQNode(data);if(NULL==q->front){q->front=newnode; }else{q->rear->next=newnode; }q->rear=newnode;q->size++; } // 隊頭出隊列 void QueuePop(Queue* q) {assert(q);if(QueueEmpty(q)){return;}else{QNode *delndoe=q->front;q->front=delndoe->next;free(delndoe);if(NULL==q->front){q->rear=NULL;}}q->size--; } // 獲取隊列頭部元素 QDataType QueueFront(Queue* q) {assert(!QueueEmpty(q));return q->front->data; } // 獲取隊列隊尾元素 QDataType QueueBack(Queue* q) {assert(!QueueEmpty(q));return q->rear->data; } // 獲取隊列中有效元素個數 int QueueSize(Queue* q) {assert(!QueueEmpty(q));return q->size; } // 檢測隊列是否為空,如果為空返回非零結果,如果非空返回0 int QueueEmpty(Queue* q) {assert(q);return NULL==q->front; } // 銷毀隊列 void QueueDestroy(Queue* q) {assert(q);QNode *cur=q->front;while(cur){q->front=cur->next;free(cur);cur=q->front;}q->rear=NULL;q->size=0; }/ void TestQueue() {Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);printf("%d\n", QueueFront(&q));printf("%d\n", QueueBack(&q));printf("%d\n", QueueSize(&q));QueuePop(&q);QueuePop(&q);QueuePop(&q);if(QueueEmpty(&q)){printf("隊列已經為空\n");}else{printf("隊列不為空\n");}QueueDestroy(&q); }main.c
#include"Queue.h"int main() {TestQueue();return 0; }三、環形隊列
假溢出問題
??正常順序隊列若進行插入和刪除,會使前部分的空間浪費,從而造成假溢出的情況。
??未解決假溢出的問題,大佬們提出了一種叫做環形隊列的結構,環形隊列可以使用數組實現,也可以使用循環鏈表實現。
??判斷循環隊列是否為空或者滿的問題,通常用(rear-front+N)%N的方法判斷是否為滿或空。
總結
- 上一篇: 08.LoT.UI 前后台通用框架分解系
- 下一篇: RTSP协议