王道数据结构——栈和队列
本文主要讲解了数据结构中操作受限的线性表:栈和队列。
知识结构如下图所示:
栈
定义
基本操作
顺序存储结构
链式存储结构
队列
定义
基本操作
顺序存储结构
链式存储结构
栈
定义:只允许在一端进行插入或删除的线性表。
栈的基本操作
InitStack(&S);初始化一个空栈
StackEmpty(&S);判断一个栈是否为空
Push(&S, x);进栈(若未满)
Pop(&S, &x);出栈(若非空)
GetTop(S, &x);读取栈顶元素(若非空,用x返回栈顶元素)
ClearStack(&S);销毁栈,并释放栈S所用的存储空间
栈的顺序存储结构
1 #include<cstdio> 2 #define Maxsize 50 3 4 typedef struct{ 5 int data[Maxsize]; 6 int top; 7 }SqStack; 8 9 void InitStack(SqStack &S){ 10 S.top = -1; 11 } 12 bool StackEmpty(SqStack &S){ 13 if(S.top == -1) 14 return true; 15 return false; 16 } 17 bool Push(SqStack &S, int x){ 18 if(S.top == Maxsize - 1) 19 return false; 20 S.data[++S.top] = x; 21 return true; 22 } 23 bool Pop(SqStack &S, int &x){ 24 if(S.top == -1) 25 return false; 26 x = S.data[S.top--]; 27 return true; 28 } 29 bool GetTop(SqStack &S, int &x){ 30 if(S.top == -1) 31 return false; 32 x = S.data[S.top]; 33 return true; 34 } 35 bool ClearStack(SqStack &S){ 36 //free(S); 37 } 38 39 int main() 40 { 41 SqStack s; 42 InitStack(s); 43 for(int i = 0; i < 10; i++) 44 if(Push(s,i)) 45 printf("%d入栈\n", i); 46 while(!StackEmpty(s)){ 47 int x; 48 GetTop(s, x); 49 printf("栈顶元素是%d\n", x); 50 if(Pop(s, x)) 51 printf("%d出栈\n", x); 52 } 53 ClearStack(s); 54 return 0; 55 }
栈的链式存储结构
1 #include<cstdio> 2 #include<cstdlib> 3 typedef struct Linknode{ 4 int data; 5 struct Linknode *next; 6 } *LiStack;//栈结点类型指针 7 8 void InitStack(LiStack &S){ 9 S = NULL; 10 } 11 bool StackEmpty(LiStack &S){ 12 if(S == NULL) 13 return true; 14 return false; 15 } 16 //不带头结点的头插法 17 bool Push(LiStack &S, int x){ 18 Linknode* n = NULL; 19 n = (Linknode*)malloc(sizeof(Linknode)); 20 if(!n) 21 return false; 22 23 n->data = x; 24 n->next = S; 25 S = n; 26 return true; 27 } 28 bool Pop(LiStack &S, int &x){ 29 if(!S) 30 return false; 31 x = S->data; 32 Linknode *p = S; 33 S = S->next; 34 free(p); 35 return true; 36 } 37 bool GetTop(LiStack &S, int &x){ 38 if(!S) 39 return false; 40 x = S->data; 41 return true; 42 } 43 bool ClearStack(LiStack &S){ 44 Linknode *p = S; 45 while(p != NULL){ 46 Linknode *t = p; 47 p = p->next; 48 free(t); 49 p = p->next; 50 } 51 free(p); 52 } 53 int main() 54 { 55 LiStack s; 56 InitStack(s); 57 for(int i = 0; i < 10; i++) 58 if(Push(s,i)) 59 printf("%d入栈\n", i); 60 while(!StackEmpty(s)){ 61 int x; 62 GetTop(s, x); 63 printf("栈顶元素是%d\n", x); 64 if(Pop(s, x)) 65 printf("%d出栈\n", x); 66 } 67 ClearStack(s); 68 return 0; 69 }
队列
定义,也是一种操作受限的线性表,只允许在表的一端进行插入,而在另一端进行删除。
基本操作
InitQueue(&Q);初始化
QueueEmpty(Q);队列是否为空
EnQueue(&Q, x);若队列未满,入队
DeQueue(&Q, &x);若队列非空,出队
GetHead(Q, &x);读取队头元素,若队列非空,将队头元素赋值给x
ClearQueue(&Q);清空队列,并回收内存
队列的顺序存储结构
1 #include<cstdio> 2 3 #define MaxSize 50 4 typedef struct{ 5 int data[MaxSize]; 6 int front,rear; 7 } SqQueue; 8 9 void InitQueue(SqQueue &Q)//初始化 10 { 11 Q.front = Q.rear = 0; 12 } 13 bool QueueEmpty(SqQueue Q)//队列是否为空 14 { 15 if(Q.front == Q.rear) 16 return true;//空为真,非空为假 17 return false; 18 } 19 bool EnQueue(SqQueue &Q, int x)//若队列未满,入队 20 { 21 //if(Q.rear == MaxSize) return false;//判断条件错误,可能假溢出 22 Q.data[Q.rear++] = x; 23 return true; 24 } 25 bool DeQueue(SqQueue &Q, int &x)//若队列非空,出队 26 { 27 if(Q.front == Q.rear) 28 return false; 29 x = Q.data[Q.front++]; 30 return true; 31 } 32 bool GetHead(SqQueue Q, int &x)//读取队头元素,若队列非空,将队头元素赋值给x 33 { 34 if(Q.front == Q.rear) 35 return false; 36 x = Q.data[Q.front]; 37 return true; 38 } 39 void ClearQueue(SqQueue &Q)//清空队列,并回收内存 40 { 41 Q.front = Q.rear = 0; 42 } 43 int main() 44 { 45 SqQueue Q; 46 InitQueue(Q); 47 for(int i = 0; i < 10; i++){ 48 if(EnQueue(Q, i)){ 49 int x; 50 GetHead(Q, x); 51 } 52 } 53 while(!QueueEmpty(Q)) 54 { 55 int x; 56 GetHead(Q, x); 57 printf("当前队头元素是%d\n", x); 58 DeQueue(Q, x); 59 printf("出队的元素是%d\n", x); 60 } 61 ClearQueue(Q); 62 return 0; 63 }
循环队列的l顺序存储结构
为了解决当队尾追上队头时判满和判空时的矛盾有三种方法,分别是
1 #include<cstdio> 2 3 #define MaxSize 10 4 /*顺序循环队列出现队尾追上队首的情况 5 方法一,牺牲一个存储空间 6 初始为Q.front == Q.rear,队满为(Q.rear + 1)%MaxSize == Q.front*/ 7 typedef struct{ 8 int data[MaxSize]; 9 int front,rear; 10 } SqQueue; 11 12 void InitQueue(SqQueue &Q)//初始化 13 { 14 Q.front = Q.rear = 0; 15 } 16 bool QueueEmpty(SqQueue Q)//队列是否为空 17 { 18 if(Q.front == Q.rear) 19 return true;//空为真,非空为假 20 return false; 21 } 22 bool EnQueue(SqQueue &Q, int x)//若队列未满,入队 23 { 24 if((Q.rear + 1)%MaxSize == Q.front) return false;//队列满 25 Q.data[Q.rear] = x; 26 Q.rear = (Q.rear + 1) % MaxSize; 27 return true; 28 } 29 bool DeQueue(SqQueue &Q, int &x)//若队列非空,出队 30 { 31 if(Q.front == Q.rear) 32 return false; 33 x = Q.data[Q.front]; 34 Q.front = (Q.front + 1) % MaxSize; 35 return true; 36 } 37 bool GetHead(SqQueue Q, int &x)//读取队头元素,若队列非空,将队头元素赋值给x 38 { 39 if(Q.front == Q.rear) 40 return false; 41 x = Q.data[Q.front]; 42 return true; 43 } 44 int Length(SqQueue Q){ 45 return (Q.rear - Q.front + MaxSize) % MaxSize; 46 } 47 void ClearQueue(SqQueue &Q)//清空队列,并回收内存 48 { 49 Q.front = Q.rear = 0; 50 } 51 int main() 52 { 53 SqQueue Q; 54 InitQueue(Q); 55 for(int i = 0; i < 15; i++){ 56 if(EnQueue(Q, i)){ 57 int x; 58 GetHead(Q, x); 59 } 60 else 61 printf("%d入队失败\n", i); 62 } 63 while(!QueueEmpty(Q)) 64 { 65 int x; 66 GetHead(Q, x); 67 printf("当前队头元素是%d\n", x); 68 DeQueue(Q, x); 69 printf("出队的元素是%d\n", x); 70 } 71 ClearQueue(Q); 72 return 0; 73 }
1 #include<cstdio> 2 #include<cstring> 3 #define MaxSize 10 4 /*顺序循环队列出现队尾追上队首的情况 5 方法二 6 初始为Q.front = Q.rear = Q.size = 0,队满为Q.size == MaxSize*/ 7 typedef struct{ 8 int data[MaxSize]; 9 int front,rear; 10 int size; 11 } SqQueue; 12 13 void InitQueue(SqQueue &Q)//初始化 14 { 15 memset(Q.data, 0, sizeof(Q.data)); 16 Q.front = Q.rear = Q.size = 0; 17 } 18 bool QueueEmpty(SqQueue Q)//队列是否为空 19 { 20 if(Q.size == 0) 21 return true;//空为真,非空为假 22 return false; 23 } 24 bool EnQueue(SqQueue &Q, int x)//若队列未满,入队 25 { 26 if(Q.size == MaxSize) return false;//队列满 27 Q.data[Q.rear] = x; 28 Q.size++; 29 Q.rear = (Q.rear + 1) % MaxSize; 30 return true; 31 } 32 bool DeQueue(SqQueue &Q, int &x)//若队列非空,出队 33 { 34 if(Q.size == 0) 35 return false; 36 x = Q.data[Q.front]; 37 Q.front = (Q.front + 1) % MaxSize; 38 Q.size--; 39 return true; 40 } 41 bool GetHead(SqQueue Q, int &x)//读取队头元素,若队列非空,将队头元素赋值给x 42 { 43 if(Q.size == 0) 44 return false; 45 x = Q.data[Q.front]; 46 return true; 47 } 48 int Length(SqQueue Q){ 49 return Q.size; 50 } 51 void ClearQueue(SqQueue &Q)//清空队列,并回收内存 52 { 53 Q.front = Q.rear = 0; 54 } 55 int main() 56 { 57 SqQueue Q; 58 InitQueue(Q); 59 for(int i = 0; i < 15; i++){ 60 if(EnQueue(Q, i)){ 61 int x; 62 GetHead(Q, x); 63 } 64 else 65 printf("%d入队失败\n", i); 66 } 67 while(!QueueEmpty(Q)) 68 { 69 int x; 70 GetHead(Q, x); 71 printf("当前队头元素是%d\n", x); 72 DeQueue(Q, x); 73 printf("出队的元素是%d\n", x); 74 } 75 ClearQueue(Q); 76 return 0; 77 }
1 #include<cstdio> 2 #include<cstring> 3 #define MaxSize 10 4 /*顺序循环队列出现队尾追上队首的情况 5 方法三 6 初始为Q.front = Q.rear = 0,tag = false 7 当Q.front == Q.rear时,tag == false 为队列插入导致队满 8 tag == true 为队列删除导致队空*/ 9 typedef struct{ 10 int data[MaxSize]; 11 int front,rear; 12 bool tag; 13 } SqQueue; 14 15 void InitQueue(SqQueue &Q)//初始化 16 { 17 memset(Q.data, 0, sizeof(Q.data)); 18 Q.front = Q.rear = 0; 19 Q.tag = false; 20 } 21 bool QueueEmpty(SqQueue Q)//队列是否为空 22 { 23 if(Q.front == Q.rear && Q.tag == false) 24 return true;//空为真,非空为假 25 return false; 26 } 27 bool EnQueue(SqQueue &Q, int x)//若队列未满,入队 28 { 29 if(Q.front == Q.rear && Q.tag == true) return false;//队列满 30 Q.data[Q.rear] = x; 31 Q.rear = (Q.rear + 1)%MaxSize; 32 Q.tag = true; //可能队满 33 return true; 34 } 35 bool DeQueue(SqQueue &Q, int &x)//若队列非空,出队 36 { 37 if(Q.front == Q.rear && Q.tag == false) 38 return false; 39 x = Q.data[Q.front]; 40 Q.front = (Q.front + 1)%MaxSize; 41 Q.tag = false; //可能队空 42 return true; 43 } 44 bool GetHead(SqQueue Q, int &x)//读取队头元素,若队列非空,将队头元素赋值给x 45 { 46 if(Q.front == Q.rear && Q.tag == false) 47 return false; 48 x = Q.data[Q.front]; 49 return true; 50 } 51 int Length(SqQueue Q){ 52 return (Q.rear - Q.front + MaxSize) % MaxSize; 53 } 54 void ClearQueue(SqQueue &Q)//清空队列,并回收内存 55 { 56 memset(Q.data, 0, sizeof(Q.data)); 57 Q.front = Q.rear = 0; 58 Q.tag = false; 59 } 60 int main() 61 { 62 SqQueue Q; 63 InitQueue(Q); 64 for(int i = 0; i < 15; i++){ 65 if(EnQueue(Q, i)){ 66 int x; 67 GetHead(Q, x); 68 } 69 else 70 printf("%d入队失败\n", i); 71 } 72 while(!QueueEmpty(Q)) 73 { 74 int x; 75 GetHead(Q, x); 76 printf("当前队头元素是%d\n", x); 77 DeQueue(Q, x); 78 printf("出队的元素是%d\n", x); 79 } 80 ClearQueue(Q); 81 return 0; 82 }
队列的链式存储结构
1 #include <cstdio> 2 #include <cstdlib> 3 typedef struct LinkNode{ 4 int data; 5 struct LinkNode *next; 6 }LinkNode; 7 typedef struct{ 8 LinkNode *front, *rear; 9 }LinkQueue; 10 11 /*初始化为带头结点的链式队列*/ 12 void InitQueue(LinkQueue &Q)//初始化 13 { 14 Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode)); 15 Q.front->next = NULL;//也即 Q.rear->next =NULL 16 } 17 bool QueueEmpty(LinkQueue Q)//队列是否为空 18 { 19 if(Q.front == Q.rear) 20 return true;//空为真,非空为假 21 return false; 22 } 23 bool EnQueue(LinkQueue &Q, int x)//若队列未满,入队 24 { 25 LinkNode *p = (LinkNode*)malloc(sizeof(LinkNode)); 26 p->data = x; 27 p->next=NULL; 28 29 Q.rear->next = p; 30 Q.rear = p; 31 return true; 32 } 33 bool DeQueue(LinkQueue &Q, int &x)//若队列非空,出队 34 { 35 if(Q.front == Q.rear) 36 return false; 37 LinkNode *p = Q.front->next; 38 x = p->data; 39 Q.front->next = p->next; 40 if(p == Q.rear) 41 Q.rear = Q.front;//原队列中只有一个结点,删除后变空 42 free(p); 43 return true; 44 } 45 bool GetHead(LinkQueue Q, int &x)//读取队头元素,若队列非空,将队头元素赋值给x 46 { 47 if(Q.front == Q.rear) 48 return false; 49 x = Q.front->next->data; 50 return true; 51 } 52 int Length(LinkQueue Q){ 53 LinkNode *p = Q.front->next;//带有头结点的形式统一 54 int cnt = 0; 55 while(p != NULL){ 56 cnt++; 57 p = p->next; 58 } 59 return cnt; 60 } 61 void ClearQueue(LinkQueue &Q)//清空队列,并回收内存 62 { 63 LinkNode *p = Q.front->next;//带有头结点的形式统一 64 while(p != NULL){ 65 LinkNode *tmp = p; 66 p = p->next; 67 free(tmp); 68 } 69 Q.front->next = Q.rear->next = NULL; 70 } 71 int main() 72 { 73 LinkQueue Q; 74 InitQueue(Q); 75 for(int i = 0; i < 10; i++){ 76 if(EnQueue(Q, i)){ 77 printf("%d入队成功\n", Q.rear->data); 78 } 79 else 80 printf("%d入队失败\n", i); 81 } 82 printf("入队后队列中元素的个数是%d\n", Length(Q)); 83 while(!QueueEmpty(Q)){ 84 int x; 85 GetHead(Q, x); 86 printf("当前队首元素%d\n", x); 87 DeQueue(Q, x); 88 printf("出队元素是%d\n", x); 89 } 90 ClearQueue(Q); 91 printf("清空后队列中元素的个数是%d\n", Length(Q)); 92 return 0; 93 }
欢迎交流,共同进步——