王道数据结构——栈和队列

本文主要讲解了数据结构中操作受限的线性表:栈和队列。

知识结构如下图所示:

  定义

  基本操作

  顺序存储结构

  链式存储结构

队列

  定义

  基本操作

  顺序存储结构

  链式存储结构

定义:只允许在一端进行插入或删除的线性表。

栈的基本操作

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 }
View Code
 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 }
View Code
 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 }
View Code

队列的链式存储结构

 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 } 

猜你喜欢

转载自www.cnblogs.com/wenzhixin/p/11723679.html