本文主要讲解了数据结构中操作受限的线性表:栈和队列。
知识结构如下图所示:
栈
定义
基本操作
顺序存储结构
链式存储结构
队列
定义
基本操作
顺序存储结构
链式存储结构
栈
定义:只允许在一端进行插入或删除的线性表。
栈的基本操作
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 }