日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构探险系列—栈篇-学习笔记

發布時間:2023/11/29 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构探险系列—栈篇-学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數據結構探險—棧篇

什么是棧?
古代棧就是牲口棚的意思。

棧是一種機制:后進先出 LIFO(last in first out)

電梯

棧要素

空棧。棧底,棧頂。沒有元素的時候,棧頂和棧底指向同一個元素,如果加入新元素,棧頂不斷升高。取出數據時棧頂不斷地降低。棧頂和棧底都稱之為棧要素。

  • 通過demo說明棧的基本原理
  • 熱身運動-進制轉換:十進制轉換到二進制,八進制,十六進制
N = (N div d) * d + N mod d
  • 步步為營- 括號匹配檢測:檢測一個字符串中的各種括號是否匹配
[()] [()()] [()[()]]

實例介紹

棧要求

mystack.h:

#ifndef MYSTACK_H #define MYSTACK_H class MyStack { public:MyStack(int size); //分配內存初始化??臻g,設定棧容量,棧頂~MyStack(); //回收??臻g內存bool stackEmpty(); //判斷棧是否為空bool stackFull(); //判斷棧是否為滿void clearStack(); //清空棧int stackLength(); //棧中元素的個數bool push(char elem); //將元素壓入棧中,棧頂上升bool pop(char &elem); //將元素推出棧,棧頂下降void stackTraverse(bool isFromButtom); //遍歷棧中元素并輸出 private:int m_iTop; //棧頂,棧中元素個數int m_iSize; //棧容量char *m_pBuffer; //棧空間指針 };#endif

mystack.cpp:

#include "Mystack.h" #include <iostream> using namespace std;MyStack::MyStack(int size) {m_iSize = size;m_pBuffer = new char[size];m_iTop = 0; } MyStack::~MyStack() {delete[]m_pBuffer;m_pBuffer = NULL;} bool MyStack::stackEmpty() {if (m_iTop == 0)//if(0 == m_iTop){return true;}else{return false;} } bool MyStack::stackFull() {if ( m_iTop == m_iSize)//>={return true;}else{return false;} }void MyStack::clearStack() {m_iTop = 0;//原棧中所有值無效 }int MyStack::stackLength() {return m_iTop; }bool MyStack::push(char elem)//放入棧頂 {if (stackFull()){return false;}m_pBuffer[m_iTop] = elem;m_iTop++;return true; } bool MyStack::pop(char &elem) {if (stackEmpty()){return false;}m_iTop--;//因為入棧時做了++,使棧頂指向下一個空位置elem = m_pBuffer[m_iTop];return true; }//char MyStack::pop() //{ // if (stackEmpty()) // { // throw 1; // } // else // { // m_iTop--; // return m_pBuffer[m_iTop]; // } //}void MyStack::stackTraverse(bool isFromButtom) {if (isFromButtom){for (int i = 0; i < m_iTop; i++){cout << m_pBuffer[i] << ",";}}else{for (int i = m_iTop - 1; i >= 0; i--){cout << m_pBuffer[i] << ",";}}}

main.cpp:

#include "Mystack.h" #include <iostream> #include <stdlib.h> using namespace std; int main(void) {MyStack *pStack = new MyStack(5);pStack->push('h');//底pStack->push('e');pStack->push('l');pStack->push('l');pStack->push('o');//頂pStack->stackTraverse(true);char elem = 0;pStack->pop(elem);cout << endl;cout << elem << endl;//pStack->clearStack();pStack->stackTraverse(false);cout << pStack->stackLength() << endl;if (pStack->stackEmpty()){cout << "棧為空" << endl;}if (pStack->stackFull()){cout << "棧為滿" << endl;}delete pStack;pStack = NULL;system("pause");return 0; }

運行結果:

棧運行結果

案例改造。

要求:


棧改造要求 #ifndef MYSTACK_H #define MYSTACK_H #include "Coordinate.h" class MyStack { public:MyStack(int size); //分配內存初始化??臻g,設定棧容量,棧頂~MyStack(); //回收??臻g內存bool stackEmpty(); //判斷棧是否為空bool stackFull(); //判斷棧是否為滿void clearStack(); //清空棧int stackLength(); //棧中元素的個數bool push(Coordinate elem); //將元素壓入棧中,棧頂上升bool pop(Coordinate &elem); //將元素推出棧,棧頂下降void stackTraverse(bool isFromButtom); //遍歷棧中元素并輸出 private:int m_iTop; //棧頂,棧中元素個數int m_iSize; //棧容量Coordinate *m_pBuffer; //棧空間指針 }; #endif#include "Mystack.h" #include <iostream> using namespace std;MyStack::MyStack(int size) {m_iSize = size;m_pBuffer = new Coordinate[size];m_iTop = 0; } MyStack::~MyStack() {delete[]m_pBuffer;m_pBuffer = NULL;} bool MyStack::stackEmpty() {if (m_iTop == 0)//if(0 == m_iTop){return true;}else{return false;} } bool MyStack::stackFull() {if ( m_iTop == m_iSize)//>={return true;}else{return false;} }void MyStack::clearStack() {m_iTop = 0;//原棧中所有值無效 }int MyStack::stackLength() {return m_iTop; }bool MyStack::push(Coordinate elem)//放入棧頂 {if (stackFull()){return false;}m_pBuffer[m_iTop] = elem;//因為這里的coordinate是一個簡單的復制。所以使用默認拷貝函數就可以了m_iTop++;return true; } bool MyStack::pop(Coordinate &elem) {if (stackEmpty()){return false;}m_iTop--;//因為入棧時做了++,使棧頂指向下一個空位置elem = m_pBuffer[m_iTop];return true; }//char MyStack::pop() //{ // if (stackEmpty()) // { // throw 1; // } // else // { // m_iTop--; // return m_pBuffer[m_iTop]; // } //}void MyStack::stackTraverse(bool isFromButtom) {if (isFromButtom){for (int i = 0; i < m_iTop; i++){//cout << m_pBuffer[i] << ",";m_pBuffer[i].printCoordinate();}}else{for (int i = m_iTop - 1; i >= 0; i--){//cout << m_pBuffer[i] << ",";m_pBuffer[i].printCoordinate();}}} #ifndef COORDINATE_H #define COORDINATE_H class Coordinate { public:Coordinate(int x=0,int y=0);void printCoordinate(); private:int m_iX;int m_iY; }; #endif#include "Coordinate.h" #include <iostream> using namespace std;Coordinate::Coordinate(int x, int y) {m_iX = x;m_iY = y; } void Coordinate::printCoordinate() {cout << "(" << m_iX << "," << m_iY << ")" << endl; }

main.cpp:

#include "Mystack.h" #include <iostream> #include <stdlib.h> using namespace std; int main(void) {MyStack *pStack = new MyStack(5);pStack->push(Coordinate(1,2));//底pStack->push(Coordinate(3, 4));pStack->stackTraverse(true);pStack->stackTraverse(false);cout << pStack->stackLength() << endl;delete pStack;pStack = NULL;system("pause");return 0; }

運行結果:

改造后運行結果

經過改造我們使棧滿足了coordinate對象的入棧出棧。

將普通棧改為類模板棧。使其可以適用于任何數據類型

類模板棧實現要求

上面我們實現過兩遍對于棧的實現。一次是實現char數組的棧。一次是實現coordinate對象的。兩次除過數據類型。差別不是很大。所以本次我們使用類模板實現適用任何數據類型的棧

mystack.h:(因為編譯器不支持類模板分開編譯。所以cpp為空)

#ifndef MYSTACK_H #define MYSTACK_H #include <iostream> using namespace std; template <typename T> class MyStack { public:MyStack(int size); //分配內存初始化??臻g,設定棧容量,棧頂~MyStack(); //回收??臻g內存bool stackEmpty(); //判斷棧是否為空bool stackFull(); //判斷棧是否為滿void clearStack(); //清空棧int stackLength(); //棧中元素的個數bool push(T elem); //將元素壓入棧中,棧頂上升bool pop(T &elem); //將元素推出棧,棧頂下降void stackTraverse(bool isFromButtom); //遍歷棧中元素并輸出 private:int m_iTop; //棧頂,棧中元素個數int m_iSize; //棧容量T *m_pBuffer; //棧空間指針 };template <typename T> MyStack<T>::MyStack(int size) {m_iSize = size;m_pBuffer = new T[size];m_iTop = 0; } template <typename T> MyStack<T>::~MyStack() {delete[]m_pBuffer;m_pBuffer = NULL;} template <typename T> bool MyStack<T>::stackEmpty() {if (m_iTop == 0)//if(0 == m_iTop){return true;}else{return false;} } template <typename T> bool MyStack<T>::stackFull() {if (m_iTop == m_iSize)//>={return true;}else{return false;} } template <typename T> void MyStack<T>::clearStack() {m_iTop = 0;//原棧中所有值無效 } template <typename T> int MyStack<T>::stackLength() {return m_iTop; } template <typename T> bool MyStack<T>::push(T elem)//放入棧頂 {if (stackFull()){return false;}m_pBuffer[m_iTop] = elem;//因為這里的coordinate是一個簡單的復制。所以使用默認拷貝函數就可以了m_iTop++;return true; } template <typename T> bool MyStack<T>::pop(T &elem) {if (stackEmpty()){return false;}m_iTop--;//因為入棧時做了++,使棧頂指向下一個空位置elem = m_pBuffer[m_iTop];return true; }//char MyStack::pop() //{ // if (stackEmpty()) // { // throw 1; // } // else // { // m_iTop--; // return m_pBuffer[m_iTop]; // } //} template <typename T> void MyStack<T>::stackTraverse(bool isFromButtom) {if (isFromButtom){for (int i = 0; i < m_iTop; i++){cout << m_pBuffer[i];//m_pBuffer[i].printCoordinate();}}else{for (int i = m_iTop - 1; i >= 0; i--){cout << m_pBuffer[i];//m_pBuffer[i].printCoordinate();}}} #endif #ifndef COORDINATE_H #define COORDINATE_H #include <ostream> using namespace std; class Coordinate {friend ostream &operator<<(ostream &out, Coordinate &coor); public:Coordinate(int x=0,int y=0);void printCoordinate(); private:int m_iX;int m_iY; }; #endif#include "Coordinate.h" #include <iostream> using namespace std;Coordinate::Coordinate(int x, int y) {m_iX = x;m_iY = y; } void Coordinate::printCoordinate() {cout << "(" << m_iX << "," << m_iY << ")" << endl; }ostream &operator<<(ostream &out, Coordinate &coor) {out << "(" << coor.m_iX << "," << coor.m_iY << ")" << endl;return out; }

main.cpp:

#include "Mystack.h" #include <iostream> #include <stdlib.h> #include "Coordinate.h" using namespace std; int main(void) {MyStack<Coordinate> *pStack = new MyStack<Coordinate>(5);pStack->push(Coordinate(1,2));//底pStack->push(Coordinate(3, 4));pStack->stackTraverse(true);pStack->stackTraverse(false);cout << pStack->stackLength() << endl;MyStack<char> *pStack2 = new MyStack<char>(5);pStack2->push('h');//底pStack2->push('e');pStack2->push('l');pStack2->push('l');pStack2->push('o');//頂pStack2->stackTraverse(true);delete pStack;pStack = NULL;system("pause");return 0; } 類模板棧運行結果

可以看到我們的類模板已經將棧改造成了通用數據類型的棧。

棧應用-進制轉換

進制轉換

短除法。不停除以進制數。保留余數。然后商繼續除以進制保留余數。直到商為0
棧的應用:將每次的余數4 0 5 2 入棧。然后從棧頂開始打印。

#ifndef MYSTACK_H #define MYSTACK_H #include <iostream> using namespace std; template <typename T> class MyStack { public:MyStack(int size); //分配內存初始化??臻g,設定棧容量,棧頂~MyStack(); //回收棧空間內存bool stackEmpty(); //判斷棧是否為空bool stackFull(); //判斷棧是否為滿void clearStack(); //清空棧int stackLength(); //棧中元素的個數bool push(T elem); //將元素壓入棧中,棧頂上升bool pop(T &elem); //將元素推出棧,棧頂下降void stackTraverse(bool isFromButtom); //遍歷棧中元素并輸出 private:int m_iTop; //棧頂,棧中元素個數int m_iSize; //棧容量T *m_pBuffer; //棧空間指針 };template <typename T> MyStack<T>::MyStack(int size) {m_iSize = size;m_pBuffer = new T[size];m_iTop = 0; } template <typename T> MyStack<T>::~MyStack() {delete[]m_pBuffer;m_pBuffer = NULL;} template <typename T> bool MyStack<T>::stackEmpty() {if (m_iTop == 0)//if(0 == m_iTop){return true;}else{return false;} } template <typename T> bool MyStack<T>::stackFull() {if (m_iTop == m_iSize)//>={return true;}else{return false;} } template <typename T> void MyStack<T>::clearStack() {m_iTop = 0;//原棧中所有值無效 } template <typename T> int MyStack<T>::stackLength() {return m_iTop; } template <typename T> bool MyStack<T>::push(T elem)//放入棧頂 {if (stackFull()){return false;}m_pBuffer[m_iTop] = elem;//因為這里的coordinate是一個簡單的復制。所以使用默認拷貝函數就可以了m_iTop++;return true; } template <typename T> bool MyStack<T>::pop(T &elem) {if (stackEmpty()){return false;}m_iTop--;//因為入棧時做了++,使棧頂指向下一個空位置elem = m_pBuffer[m_iTop];return true; }//char MyStack::pop() //{ // if (stackEmpty()) // { // throw 1; // } // else // { // m_iTop--; // return m_pBuffer[m_iTop]; // } //} template <typename T> void MyStack<T>::stackTraverse(bool isFromButtom) {if (isFromButtom){for (int i = 0; i < m_iTop; i++){cout << m_pBuffer[i];//m_pBuffer[i].printCoordinate();}}else{for (int i = m_iTop - 1; i >= 0; i--){cout << m_pBuffer[i];//m_pBuffer[i].printCoordinate();}}} #endif#include "Mystack.h" #include <iostream> #include <stdlib.h> using namespace std;#define BINARY 2 #define OCTONARY 8 #define HEXADECIMAL 16int main(void) {MyStack<int> *pStack = new MyStack<int>(30);int N = 1348;int mod = 0;while (N !=0){mod = N % BINARY;pStack->push(mod);N = N / BINARY;}pStack->stackTraverse(false);delete pStack;pStack = NULL;system("pause");return 0; }

二進制和8進制都沒有問題了,16進制還需要進一步改造。

運行結果:

!運行結果](http://upload-images.jianshu.io/upload_images/1779926-c6c62f86ff27da42.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

16進制改造

mystack.h與原來一致。

#include "Mystack.h" #include <iostream> #include <stdlib.h> using namespace std;#define BINARY 2 #define OCTONARY 8 #define HEXADECIMAL 16int main(void) {char num[] = "0123456789ABCDEF";MyStack<char> *pStack = new MyStack<char>(30);int N = 2016;int mod = 0;while (N !=0){mod = N % HEXADECIMAL;pStack->push(num[mod]);N = N / HEXADECIMAL;}pStack->stackTraverse(false);/*for (int i=pStack->stackLength()-1;i>=0;i--){num[pStack[i]]}*//*int elem = 0;while (!pStack->stackEmpty()){pStack->pop(elem);cout << num[elem];}*/delete pStack;pStack = NULL;system("pause");return 0; }

如果仍使棧為int型。則可以使用注釋部分打印出內容。修改為char之后??墒褂?br />pStack->push(num[mod]);

棧應用括號匹配

括號匹配

從前往后掃描。左方括號入棧,左圓括號入棧,當遇到右括號則左圓括號出棧。當遇到右方括號,左方括號出棧。字符串掃描完畢時棧為空則全部匹配。棧中還有東西則不是全部匹配

#include "Mystack.h" #include <iostream> #include <stdlib.h> using namespace std;int main(void) {MyStack<char> *pStack = new MyStack<char>(30);//已存入的字符MyStack<char> *pNeedStack = new MyStack<char>(30);//需要的字符。char str[] = "[()]]";char currentNeed = 0;for (int i=0;i<strlen(str);i++){if (str[i] != currentNeed)//如果此時掃描到的字符不是我們所需要的。{pStack->push(str[i]);//那么將這個字符存入“已存入字符”switch (str[i])//對于這個字符,生成它的currentneed{case '[':if (currentNeed !=0)//如果currentneed已經有值,不為初值。{pNeedStack->push(currentNeed);//將當前的需要字符入棧。}currentNeed = ']';//生成當前需要。break;case '(':if (currentNeed != 0){pNeedStack->push(currentNeed);}currentNeed = ')';break;default:cout << "字符串不匹配" << endl;system("pause");return 0;}}else{char elem;pStack->pop(elem);if (pNeedStack->pop(currentNeed)){currentNeed = 0;}}}if (pStack->stackEmpty()){cout << "字符串括號匹配" << endl;}delete pStack;pStack = NULL;delete pNeedStack;pNeedStack = NULL;system("pause");return 0; }

運行過程:

最開始:currentneed為0.

  • str[0]為"[",此時需要的currentneed為0,不相等。
  • 進入if內部。將"[" 存入棧1。進入switch的case內部。匹配到case:"["
  • 此時判斷到當前的currentneed = 0.不滿足if。則生成currentneed "]"。并break
    出循環。
  • str[1]為"(",此時需要的currentneed是"]",不相等。
  • 進入if內部將"("存入棧1.進入switch的case內部。匹配到case:"("
  • 此時判斷到當前的currentneed ="]"不等于0.將該字符存入需要棧,因為下面就要對他進行覆蓋了、
  • 生成新的的currentneed")",并break出循環
  • str[2]為")",正好與我們當前的currentneed一致。
  • 那么我們將棧一的"("彈出。并將needstack里的上一個急需的賦值給currentneed。
  • 進入下一次循環。

也就是currentneed變量里面存放的是當前下一次循環剛開始急需匹配的。
need棧里存放的是歷史需要的。

當當前需要的和正在掃描的一致。則將棧1中出棧。

總結

以上是生活随笔為你收集整理的数据结构探险系列—栈篇-学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。