IT评测·应用市场-qidao123.com技术社区

标题: 数据结构 栈 [打印本页]

作者: 乌市泽哥    时间: 2025-1-24 20:21
标题: 数据结构 栈
目次
前言
一,栈的基本先容与定义
二,数组实现栈
三,链表实现栈
 四,栈的应用
总结

前言

我们学习了链表,接下来我们就来学习栈,我将会从栈的先容到实现栈与栈的全部的功能


   一,栈的基本先容与定义

  栈( Last In First Out :最先进来的最先出去)
  简称:LIFO
  1,栈的属性
  最先进来的元素末了进去,可以抽象为我们现实中放东西,每次访问栈的元素的时候,只可以访问站的顶部(任何元素都是只可以从最顶部进行插入和删除等一系列的操纵)
  
可以类似于羽毛球筒,先放进去末了拿出来
  假如实在难以明白,可以去阅读我的文章,函数栈帧,这些都是必备的知识
  
  2,栈的定义
  栈是一个列表或者集合,它有如许的一种限制,插入,删除只能从一段进行,而这个操纵的位置我们称为栈顶
  基本操纵:
  1  push( 插入 )   2  pop( 弹出 )   3  top( 返回栈顶元素 )   4  empty( 是否为空 )
  时间复杂度O( n )
  
  3,操纵的实际环境
  

  这个就是我们再实际操纵栈的过程,每个函数都是有着本身的作用,我们只需要根据函数进行本身想要的操纵就好了,STL库内里是有给stack这个类的,可以直接调用并使用
  
  4,实际应用
  ————可以用来帮助我们实验函数
  ————递归
  ————编译器的撤销操纵
  ————编译器内里的括号操纵( 如: {  }     [  ]    (  ) )
  
   二,数组实现栈

  1,插入与删除
  
  伪代码头脑
  

  我创建一个数组,此时此刻当数组为空栈的时候,有一个top指针是再-1处的,然后我们插入数据的时候,也是只可以再栈顶插入,只要再A[ top ]处添加元素,我们栈是用来存储暂时数据的,不会恒久生存,以是我们并不消把刚刚开始初始化在0处的值给删除,直接把栈顶今后移动,使用下一次赋值占上去就好了,这个就是栈的性质
  这里我们栈的时间复杂度是O( 1 )
  最好的环境是O( 1 ),最坏的环境是O( n ),均匀下来就是O( 1 )了
  其他的功能
  返回栈顶元素
  1. Top( ){ return A[ top ]; }
复制代码
检查是否为空 
  1. Isempty( ){
  2. if( top==-1)return true;
  3. else return fasle; }
复制代码
2,模仿实现
  
  1. #include<iostream>
  2. using namespace std;
  3. #define MAX_SIZE 100
  4. int A[MAX_SIZE];
  5. int top = -1;
  6. void push(int x) {
  7.         if (top == MAX_SIZE) {
  8.                 cout << "stack overflow" << endl;
  9.                 return;
  10.         }
  11.         A[++top] = x;
  12. }
  13. void pop() {
  14.         if (top == -1) {
  15.                 cout << "NO element to pop" << endl;
  16.                 return;
  17.         }
  18.         top--;
  19. }
  20. int Top() {
  21.         if (top == -1) {
  22.                 cout << "NO element in the stack" << endl;
  23.                 return 0;
  24.         }
  25.         return A[top];
  26. }
  27. void IsEmpty() {
  28.         if (top == -1) {
  29.                 cout << "Stack is empty" << endl;
  30.         }
  31.         else {
  32.                 cout << "Stack not is empty" << endl;
  33.         }
  34. }
  35. void print() {
  36.         int i = 0;
  37.         for (i = top;i >= 0;i--) {
  38.                 cout << A[i] << endl;
  39.         }
  40. }
  41. int main() {
  42.         push(2);
  43.         push(3);
  44.         push(78);
  45.         push(89);
  46.         IsEmpty();
  47.         pop();
  48.         print();
  49.         return 0;
  50. }
复制代码
分别模仿了push插入   pop弹出   top返回栈顶元素   isempty是否为空
  
  push插入:     就是使用数组下角标进行索引,然后把值放入到对应的位置,记得top的值要1改变
  pop弹出:       就是使用top--来是实现打印的具体位置,记得栈是不需要删除原本在那边的值的
  top返回栈顶: 就是使用return返回A[ top ]即可
  isempty检查: 就是我们使用top的值,这个栈顶的值还是原来的谁人值就是为空了
    三,链表实现栈

  我们使用链表的话,由于栈只可以在栈顶进行插入与删除,以是我们要选择一端作为栈顶,以是有两种方法,一种是头插法还有一种是尾插法,由于头插法的时间复杂度是O( 1 )而尾插法的时间复杂度是O( n )以是我们选择头插法
  

  这个实现就是链表的头插法罢了 
  1. #include<iostream>
  2. #include<new>
  3. using namespace std;
  4. struct Node {
  5.         int data;
  6.         struct Node* Next;
  7. };
  8. Node *head;
  9. void insert(int a) {
  10.         Node* temp = new Node;
  11.         temp->data = a;
  12.         temp->Next = head;
  13.         head = temp;
  14. }
  15. void print() {
  16.         Node* a = head;
  17.         while (a != NULL) {
  18.                 cout << a->data << " ";
  19.                 a = a->Next;
  20.         }
  21. }
  22. int main() {
  23.         Node* temp1 = new Node;
  24.         Node* temp2 = new Node;
  25.         Node* temp3 = new Node;
  26.         temp1->data = 1;
  27.         temp2->data = 2;
  28.         temp3->data = 3;
  29.         head = temp1;
  30.         temp1->Next = temp2;
  31.         temp2->Next = temp3;
  32.         temp3->Next = NULL;
  33.        
  34.         insert(4);
  35.         print();
  36. }
复制代码
这个代码很好明白,也就是头插法,很简单
     四,栈的应用

  1,反转一个字符串
  
  

  我们用c++来实现栈来打印这个字符串
  再STL库内里是提供stack的,以是我们只需要引用这个头文件就好了
  1. #include<iostream>
  2. #include<stack>
  3. using namespace std;
  4. char str[6] = "hello";
  5. void Reverse() {
  6.         stack<char>S;
  7.         for (int i = 0;i < 5;i++) {
  8.                 S.push(str[i]);
  9.         }
  10.         for (int i = 0;i < 5;i++) {
  11.                 str[i] = S.top();
  12.                 S.pop();
  13.         }
  14. }
  15. int main() {
  16.         Reverse();
  17.         for (int i = 0;i < 5;i++)
  18.                 cout << str[i];
  19.         return 0;
  20. }
复制代码
我们即使没有学习过STL库,但是这里可以进行简单的记忆,stack<类型>名字,然后这是一个类,类跟结构体是差不多的,以是直接用成员运算符就好了,内里的函数的作用跟上面所讲的是一样的
  当然这个不是最优解对于反转字符串,但是是很简答的,我们还有另外一个方法比这个方法更高效
  

  这里用两个指针分别指向头和尾,然后进行交换,有奇数环境和偶数环境,然后进行交换就好了,这个服从比谁人更高,这里就不写代码了,这里重要是讲栈,提供一个思路,虽然时间复杂度都是O( n ),但是空间复杂度这个方法更少
  
  2,反转一个链表
  
  1. #include<iostream>
  2. #include<stack>
  3. using namespace std;
  4. struct Node {
  5.         int data;
  6.         Node* Next;
  7. };
  8. Node* head;
  9. void Reverse() {
  10.         Node* temp = head;
  11.         stack<Node*>S;
  12.         while (temp != NULL) {
  13.                 S.push(temp);
  14.                 temp = temp->Next;
  15.         }
  16.         temp = S.top();
  17.         head = temp;
  18.         while (!S.empty()) {
  19.                 temp->Next = S.top();
  20.                 S.pop();
  21.                 temp = temp->Next;
  22.         }
  23.         temp->Next = NULL;
  24. }
  25. void print() {
  26.         Node* temp = head;
  27.         while (temp != NULL) {
  28.                 cout << temp->data << "  ";
  29.                 temp = temp->Next;
  30.         }
  31. }
  32. int main() {
  33.         head = NULL;
  34.         Node* temp1 = new Node;
  35.         temp1->data = 1;
  36.         temp1->Next = NULL;
  37.         Node* temp2 = new Node;
  38.         temp2->data = 2;
  39.         temp2->Next = NULL;
  40.         Node* temp3 = new Node;
  41.         temp3->data = 3;
  42.         temp3->Next = NULL;
  43.         Node* temp4 = new Node;
  44.         temp4->data = 4;
  45.         temp4->Next = NULL;
  46.         temp1->Next = temp2;  temp2->Next = temp3;  temp3->Next = temp4;
  47.         head = temp1;
  48.          Reverse();
  49.          print();
  50. }
复制代码
这里我们的stack设置的是Node*类型,那么为什么设置为这个呢?
  
   总结:
  1,你要存储的是这个节点,而不是这个节点的指针
              2,假如真的是存储了节点,那么就加大了内存的开销,由于你有添加了一个副本,假如用指针就可以减少内存的开销
              3,避免深度拷贝,就是为了减少复杂性,我们把这个栈内里直接存储地址,开释也很好开释
              4,誊写雅观,由于你可以用->这个符号,可以统一
  
  3,检查括号的匹配性
  
  思路:我们只需要把左括号放入栈内里,然后检测右括号,假如终极栈为空或者由括号匹配不上就直接暴非常就好了,由于你放括号的顺序一定是和你匹配括号的顺序是一样的,这里就讲解思路,读者可以下去本身写写代码
  
总结

我们先容了栈的基本定义和先容
然后分别用数组和链表来实现栈
末了展现了栈的应用
总的来说,栈就是得当反转某个东西,由于你放进去永世与你拿出来是相反的,还可以使用栈来检查对称性

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4