数据结构 - 栈和队列

数据结构 - 栈和队列

介绍

  • 栈和队列是两种很简单, 但也很重要的数据结构, 在之后的内容也会用到的
  • 栈的特点就是FILO(first in last out)
  • 而队列则是FIFO(first in first out)

栈和队列也是列表

  • 栈和队列都可以认为是链表, 只是插入删除的方式做了改变
  • 栈的插入删除都在尾部, 如果是头插法的话, 则是在头部
  • 队列的插入在尾部, 删除在头部

栈的两种实现方式

数组

  • 第一种 - 数组, 对于知道了栈最大长度的情况, 我建议用数组
 
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MaxLength = 10000 + 20;
 4 
 5 struct Stack {
 6     int s[MaxLength];
 7     int index;
 8 
 9     Stack():index(0){}
10     bool Empty(){  return index == 0;  }
11     void Push(int d){  s[index++] = d;  }
12     void Pop(){
13         if (index)  --index;
14         else    printf("Stack is Empty!\n");
15     }
16     int Top(){
17         if (index)  return s[index - 1];
18         else {
19             printf("Stack is Empty!!!\n");
20             return -1;
21         }
22     }
23     void Clear(){  index = 0;  }
24     void Print() {
25         for (int i = 0; i < index - 1; i++)
26             printf("%d ", s[i]);
27         if (index)  printf("%d\n", s[index - 1]);
28     }
29 };
30 
31 int main () {
32     int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
33     Stack myStack;
34     for (int i = 0; i < 10; i++)    myStack.Push(a[i]);
35 
36     myStack.Print();
37     myStack.Push(11);
38     myStack.Print();
39     printf("top = %d\n", myStack.Top());
40     myStack.Pop();
41     myStack.Pop();
42     myStack.Pop();
43     myStack.Print();
44     myStack.Clear();
45     myStack.Pop();
46     myStack.Top();
47     return 0;
48 }

链表

  • 第二种 - 链表, 对于不知道最大长度情况可以用
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct Node {
 5     int data;
 6     Node *next;
 7     Node(int d, Node *nxt = nullptr):data(d), next(nxt){}
 8 };
 9 
10 ///创建栈, 并用头插法插入dat的前n个元素
11 Node* Create(int n, int dat[]) {
12     Node *head = new Node(-1);
13 
14     for (int i = 0; i < n; i++) {
15         head -> next = new Node(dat[i], head -> next);
16     }
17     return head;
18 }
19 
20 ///在栈的头部添加dat
21 void Push(Node *head, int dat) {
22     head -> next = new Node(dat, head -> next);
23 }
24 
25 ///判断栈是否为空
26 bool Empty(Node *head) {
27     return head -> next == nullptr;
28 }
29 
30 ///弹出栈的第一个元素-栈顶元素
31 void Pop(Node *head) {
32     if (head -> next)   head -> next = head -> next -> next;
33     else    printf("栈已为空, 无法再弹出元素!\n");
34 }
35 
36 ///返回栈顶元素, 不删除
37 int Top(Node *head) {
38     if (head -> next)   return head -> next -> data;
39     else    printf("栈已为空, 无栈顶元素!\n");
40 }
41 
42 ///清空栈
43 void Clear(Node *head) {
44     head -> next = nullptr;
45 }
46 
47 ///输出栈, 由于是头插法, 所以这里用一下递归
48 ///递归其实也用到了栈
49 void Print(Node *head) {
50     if (head -> next) {
51         Print(head -> next);
52         printf(" %d", head -> data);
53     } else  printf("%d", head -> data);
54 }
55 
56 ///用这个函数补一个回车
57 void PrintStack(Node *head) {
58     Print(head -> next);
59     printf("\n");
60 }
61 
62 int main () {
63     int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
64     Node *head = Create(10, a);
65     PrintStack(head);
66     Push(head, 11);
67     PrintStack(head);
68     printf("top = %d\n", Top(head));
69     Pop(head);
70     Pop(head);
71     Pop(head);
72     PrintStack(head);
73     Clear(head);
74     Pop(head);
75     Top(head);
76     return 0;
77 }

队列的两种实现方式

数组

  • 第一种, 数组, 在知道队列最大长度时, 使用数组会很简单
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MaxLength = 10000 + 20;
 4 
 5 struct Queue {
 6     int myQueue[MaxLength];
 7     int head, tail;
 8 
 9     Queue():head(0), tail(0){}
10 
11     bool Empty() {
12         return head == tail;
13     }
14 
15     void Push(int dat) {
16         myQueue[tail++] = dat;
17     }
18 
19     void Pop() {
20         if (head != tail)   head++;
21         else    printf("This Queue is Empty!!\n");
22     }
23 
24     void Clear() {
25         head = tail = 0;
26     }
27 
28     int Front() {
29         if (!Empty())   return myQueue[head];
30         else    printf("The Queue is Empty!\n");
31     }
32 
33     void Print() {
34         if (Empty())    printf("Queue is Empty!!!\n");
35         else {
36             for (int i = head; i < tail - 1; i++)   printf("%d ", myQueue[i]);
37             printf("%d\n", myQueue[tail - 1]);
38         }
39     }
40 };
41 
42 int main () {
43     int a[10] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 4};
44     Queue Q;
45     for (int i = 0; i <10; i++)    Q.Push(a[i]);
46     Q.Print();
47     printf("front is : %d\n", Q.Front());
48 
49     Q.Pop();    Q.Pop();    Q.Pop();
50     Q.Print();
51 
52     Q.Clear();
53     Q.Print();
54 
55     return 0;
56 }

链表

  • 第二种, 链表, 在不知道队列最大长度时可以使用, 我觉得很麻烦
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct Node {
 5     int data;
 6     Node *next;
 7     Node(int d, Node *nxt = nullptr):data(d), next(nxt){}
 8 };
 9 
10 Node* CreateQueue(int n, int dat[]) {
11     Node *head = new Node(-1);
12     Node *temp = head;
13 
14     for (int i = 0; i < n; i++) {
15         temp -> next = new Node(dat[i]);
16         temp = temp -> next;
17     }
18     return head;
19 }
20 
21 void Push(Node *head, int dat) {
22     Node *temp = head;
23     while (temp -> next)    temp = temp -> next;
24     temp -> next = new Node(dat);
25 }
26 
27 bool Empty(Node *head) {
28     return head -> next == nullptr;
29 }
30 
31 void Pop(Node *head) {
32     if (head -> next)   head -> next = head -> next -> next;
33     else printf("This Queue is Empty!\n");
34 }
35 
36 void Clear(Node *head) {
37     head -> next = nullptr;
38 }
39 
40 int Front(Node *head) {
41     if (head -> next)   return head -> next -> data;
42     else    printf("This Queue is Empty!!!\n");
43 }
44 
45 void Print(Node *head) {
46     Node *temp = head -> next;
47     if (temp) {
48         while (temp -> next) {
49             printf("%d ", temp -> data);
50             temp = temp -> next;
51         }
52         printf("%d\n", temp -> data);
53     } else  printf("Queue is Empty!\n");
54 }
55 
56 int main () {
57     int a[10] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 4};
58     Node *Q = CreateQueue(10, a);
59     Print(Q);
60     printf("Queue is Empty? : %s\n", Empty(Q) ? "true" : "false");
61     while (!Empty(Q))   Pop(Q);
62     Print(Q);
63     for (int i = 0; i < 10; i++)    Push(Q, a[i]);
64     Print(Q);
65     return 0;
66 }

小结

  • 对于一个惯用数组的我来说, 我当然是喜欢用数组了, 然而在实际上, 我会直接用STL里面的queue, 栈的话, 我还用得比较少, 队列用得比较多
  • 从这个码量都看得出来, 数组实现的栈和队列实在是非常的简单, 所以我觉得只看数组的就够了
 

猜你喜欢

转载自www.cnblogs.com/123zhh-helloworld/p/10080837.html