栈和队列数据结构的特点,啥情况下用到栈,啥情况下用到队列(各举3个例子)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈和队列数据结构的特点,啥情况下用到栈,啥情况下用到队列(各举3个例子)相关的知识,希望对你有一定的参考价值。

谁能帮忙总结下,自己总结不完整

栈:特点就是一个先进后出的结构。
队列:特点就是一个先进先出的结构。
//一般只要你满足这个特点就可以称之为栈或队列。
栈的应用:非常广泛,在CPU内部就有提供栈这个机制。主要用途:函数调用和返回,数字转字符,表达式求值,走迷宫等等。在CPU内部栈主要是用来进行子程序调用和返回,中断时数据保存和返回。在编程语言中:主要用来进行函数的调用和返回。可以说在计算机中,只要数据的保存满足先进后出的原理,都优先考虑使用栈,所以栈是计算机中不可缺的机制。
队列的应用:队列主要用在和时间有关的地方,特别是操作系统中,队列是实现多任务的重要机制。windows中的消息机制就是通过队列来实现的。进程调度也是使用队列来实现,所以队列也是一个重要的机制。只要满足数据的先进先出原理就可以使用队列。
参考技术A 栈的特点:操作受限,只能在表的一端进行插入、删除,是先进后出的线性表。算符优先算法求表达式的值、表达式的括号匹配问题、迷宫求解、进制转换等问题都具有先进后出的特点,需使用栈结构。
队列的特点:操作受限,只能在表的一端插入,另一端删除,是先进先出的线性表。舞伴问题、操作系统的进程|作业管理中的先进先出服务、字符序列是否回文等由于具有先进先出的特点,需要使用队列结构。
参考技术B

栈和队列数据结构的特点是:

    栈特点就是一个先进后出的结构。

    队列特点就是一个先进先出的结构。

栈和队列的区别是:

    数据结构不同队列先进先出,栈先进后出。

    对插入和删除操作的"限定"。 栈是限定只能在表的一端进行插入和删除操作的线性表。      队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。

    遍历数据速度不同。栈只能从头部取数据 也就最先放入的需要遍历整个栈最后才能取出来,而且在遍历数据的时候还得为数据开辟临时空间,保持数据在遍历前的一致性队列怎不同,他基于地址指针进行遍历,而且可以从头或尾部开始遍历,但不能同时遍历,无需开辟临时空间。

数据结构 - 栈和队列

数据结构 - 栈和队列

介绍

  • 栈和队列是两种很简单, 但也很重要的数据结构, 在之后的内容也会用到的
  • 栈的特点就是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!
");
15     }
16     int Top(){
17         if (index)  return s[index - 1];
18         else {
19             printf("Stack is Empty!!!
");
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
", 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
", 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("栈已为空, 无法再弹出元素!
");
34 }
35 
36 ///返回栈顶元素, 不删除
37 int Top(Node *head) {
38     if (head -> next)   return head -> next -> data;
39     else    printf("栈已为空, 无栈顶元素!
");
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("
");
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
", 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!!
");
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!
");
31     }
32 
33     void Print() {
34         if (Empty())    printf("Queue is Empty!!!
");
35         else {
36             for (int i = head; i < tail - 1; i++)   printf("%d ", myQueue[i]);
37             printf("%d
", 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
", 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!
");
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!!!
");
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
", temp -> data);
53     } else  printf("Queue is Empty!
");
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
", 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, 栈的话, 我还用得比较少, 队列用得比较多
  • 从这个码量都看得出来, 数组实现的栈和队列实在是非常的简单, 所以我觉得只看数组的就够了
 

以上是关于栈和队列数据结构的特点,啥情况下用到栈,啥情况下用到队列(各举3个例子)的主要内容,如果未能解决你的问题,请参考以下文章

在啥情况下用session?啥情况下用hidden?

asp.net三层架构与asp.net MVC各自的区别,各自应该应用在啥场合,在啥情况下用三层,啥情况下用MVC

Java中的构造方法与普通方法的区别? 啥情况下用构造方法啥情况下用普通的方法

c#中啥情况用abstract,啥情况下用virtual

请教C#中String.Format 有啥作用?啥情况下用它呢?

SQL中啥情况下用引号