資料結構_棧
阿新 • • 發佈:2018-12-15
點選一下吧hh
棧是特殊的線性表,特點:先進後出~~
直接用STL很方便的,不過還是從底層重新學一遍吧。
如果你是為了找程式碼,應付老師的作業,建議右上角關掉視窗。
關於棧的一些操作
棧的順序儲存結構
#include <iostream> #include <cstring> #include <string> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <set> #include <map> #include <cstdlib> #define ll long long #define stack_maxsize 500 #define Selemtype int #define Status int #define False 0 #define OK 1 using namespace std; typedef struct { Selemtype data[stack_maxsize]; int top; }sq_stack; //當存在第一個資料時,top=0,所以把空棧的top設為-1 Status init_stack(sq_stack &S)//待完善 { S.top=-1; return OK; } //銷燬 //Status destory_stack(sq_stack &S); //清空 Status clear_stack(sq_stack &S) { S.top=-1; return OK; } //判斷是否為空 Status empty_stack(sq_stack &S) { if(S.top==-1) return OK; return False; } //棧的長度 Status length_stack(sq_stack S) { if(!empty_stack(S)) return S.top+1; else return False; } //出棧 Status pop_stack(sq_stack &S,Selemtype *e) { if(S.top==-1) return False; *e=S.data[S.top]; S.top--; return OK; } //入棧 Status push_stack(sq_stack &S,Selemtype e) { if(S.top==stack_maxsize-1) return False; S.top++;//棧頂指標加+ S.data[S.top]=e; //入棧 return OK; } //獲得棧頂元素 Status top_stack(sq_stack S,Selemtype *e) { if(!empty_stack(S)) { *e=S.data[S.top]; return OK; }else return False; } //遍歷 void traverse_stack(sq_stack S) { for(int i=0;i<=S.top;i++) { cout<<S.data[i]<<" "; } cout<<endl; } int main() { int n; sq_stack S; Selemtype e; init_stack(S); cout<<"input the number of pushing: "; cin>>n; //入棧 for(int i=0;i<n;i++) { int c=rand()%10+1; push_stack(S,c); } //遍歷 cout<<"low->top: "; traverse_stack(S); //長度 cout<<"the length of stack: "; cout<<length_stack(S)<<endl; //出棧 cout<<"pop: "; pop_stack(S,&e); cout<<e<<endl; //入棧 cout<<"input number you want to push: "; cin>>e; push_stack(S,e); //入棧之後的測試 cout<<"after pushing:"; cout<<"low->top: "; traverse_stack(S); cout<<"the length of stack: "; cout<<length_stack(S)<<endl; cout<<"the number of top: "; top_stack(S,&e); cout<<e<<endl; cout<<"clear_stack…ing…"<<endl; if(clear_stack(S)) { cout<<"clear finished!!!!!"<<endl; } else cout<<"error"<<endl; return 0; }
棧的鏈式儲存結構
/* malloc : (返回指標型別)malloc(申請空間大小,一般是型別個數×sizeof(型別)) */ #include <iostream> #include <cstring> #include <string> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <set> #include <map> #include <cstdlib> #define ll long long #define stack_size 100 #define stackincrement 10 #define Selemtype int #define Status int #define False 0 #define OK 1 using namespace std; typedef struct { Selemtype *base;//在棧構造之前和毀滅之後 base 的值為 null Selemtype *top;//棧頂指標(非空棧中的棧頂指標始終在棧頂元素的下一個位置) int stacksize;//當前已經分配的儲存空間 }sq_stack; //!!!!!! base top 可是兩個指標啊 !!!!! //初始化 Status init_stack(sq_stack &S) { S.base=(Selemtype *)malloc(stack_size*sizeof(Selemtype)); if(!S.base) return False; S.top=S.base; S.stacksize=stack_size; } //銷燬 棧 S Status destory_stack(sq_stack &S) { //if(S.base) //{ // S.base=NULL; // return OK; //} S.top==S.base; free(S.base);//注意!釋放的不是指標,而是指標指向的空間記憶體~~~~ S.base=NULL;//然後指標指向空 S.top=NULL; return OK; } //置為空棧 Status clear_stack(sq_stack &S) { S.top=S.base; S.stacksize=0; return OK; } //判斷是否為空棧 Status empty_stack(sq_stack S) { if(S.base==S.top) return OK; else return False; } //棧的長度 Status length_stack(sq_stack S) { if(S.base==NULL||S.base==S.top) return False; else return (S.top-S.base); } //pop 出棧 Status pop_stack(sq_stack &S,Selemtype &e) { if(empty_stack(S)) return False; S.top--; e=*(S.top); return OK; } //push 入棧 e入棧 Status push_stack(sq_stack &S,Selemtype e) { if(S.top-S.base>=S.stacksize)//空間不夠 要拓展空間 { S.base=(Selemtype *)malloc((S.stacksize+stackincrement)*sizeof(Selemtype)); if(!S.base) return False; S.top=S.base+S.stacksize; S.stacksize+=stackincrement; } *S.top=e; S.top++; return OK; } //get.top 操作 Status get_top(sq_stack S,Selemtype &e) { if(empty_stack(S)) return False; e=*(S.top-1); return OK; } //從棧底到棧頂依次 輸出每個元素 void traverse_stack(sq_stack S) { if(empty_stack(S)) cout<<"Error"<<endl; else { while(S.top!=S.base) { cout<<*(S.top-1)<<" "; S.top--; } cout<<endl; } } int main() { int e; sq_stack S; if(init_stack(S)) { cout<<"Initialization is completed!"<<endl; }else { cout<<"Error"<<endl; return 0; } //入棧: for(int i=1;i<=10;i++) { push_stack(S,i*2); } //長度 cout<<"The length of stack: "<<length_stack(S)<<endl; //得到棧頂元素 if(get_top(S,e)) { cout<<"The top of element: "<<e<<endl; }else cout<<"Error"<<endl; //出棧 //cout<<"out: "<<endl; //while(pop_stack(S,e)) //{ // cout<<e<<" "; //} //cout<<endl; //遍歷棧裡面的元素: cout<<"traverse: "; traverse_stack(S); //再次得到棧頂元素 (從這點可以知道,traverse_stack 並沒有對棧中元素 做出棧 操作,只是指標在動,資料並沒有消失) if(get_top(S,e)) { cout<<"The top of element: "<<e<<endl; } else cout<<"Error"<<endl; //入棧 //cout<<"Input an element you want to insert: "; int flag=1; while(flag) { cout<<"Input an element you want to insert: "; char c; cin>>e; push_stack(S,e); traverse_stack(S); cout<<"continue pushing??? (Y or N)"<<endl; cin>>c; if(c=='Y'||c=='y') flag=1; else flag=0; } //出棧 int flag1=1; cout<<"out: "; while(flag1) { char c; if(pop_stack(S,e)) { cout<<e<<endl<<endl; } cout<<"continue outing??? (Y or N)"<<endl; cin>>c; if(c=='Y'||c=='y') flag1=1; else flag1=0; } //清空 if(clear_stack(S)) { //traverse_stack(S); // 判斷是否為空 if(empty_stack(S)) cout<<"Emptying is done!"<<endl; else cout<<"error"<<endl; }else cout<<"error"<<endl; //銷燬 if(destory_stack(S)) { cout<<"destory finished!"<<endl; } return 0; }
棧的應用舉例: 進位制轉換
#include <iostream> #include <cstring> #include <string> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <set> #include <map> #include <cstdlib> #define ll long long #define stack_size 100 #define stackincrement 10 #define Selemtype int #define Status int #define False 0 #define OK 1 using namespace std; typedef struct { Selemtype *base;//在棧構造之前和毀滅之後 base 的值為 null Selemtype *top;//棧頂指標(非空棧中的棧頂指標始終在棧頂元素的下一個位置) int stacksize;//當前已經分配的儲存空間 }sq_stack; //!!!!!! base top 可是兩個指標啊 !!!!! //初始化 Status init_stack(sq_stack &S) { S.base=(Selemtype *)malloc(stack_size*sizeof(Selemtype)); if(!S.base) return False; S.top=S.base; S.stacksize=stack_size; } //銷燬 棧 S Status destory_stack(sq_stack &S) { //if(S.base) //{ // S.base=NULL; // return OK; //} S.top==S.base; free(S.base);//注意!釋放的不是指標,而是指標指向的空間記憶體~~~~ S.base=NULL;//然後指標指向空 S.top=NULL; return OK; } //置為空棧 Status clear_stack(sq_stack &S) { S.top=S.base; S.stacksize=0; return OK; } //判斷是否為空棧 Status empty_stack(sq_stack S) { if(S.base==S.top) return OK; else return False; } //棧的長度 Status length_stack(sq_stack S) { if(S.base==NULL||S.base==S.top) return False; else return (S.top-S.base); } //pop 出棧 Status pop_stack(sq_stack &S,Selemtype &e) { if(empty_stack(S)) return False; S.top--; e=*(S.top); return OK; } //push 入棧 e入棧 Status push_stack(sq_stack &S,Selemtype e) { if(S.top-S.base>=S.stacksize)//空間不夠 要拓展空間 { S.base=(Selemtype *)malloc((S.stacksize+stackincrement)*sizeof(Selemtype)); if(!S.base) return False; S.top=S.base+S.stacksize; S.stacksize+=stackincrement; } *S.top=e; S.top++; return OK; } //get.top 操作 Status get_top(sq_stack S,Selemtype &e) { if(empty_stack(S)) return False; e=*(S.top-1); return OK; } //從棧底到棧頂依次 輸出每個元素 void traverse_stack(sq_stack S) { if(empty_stack(S)) cout<<"Error"<<endl; else { while(S.top!=S.base) { cout<<*(S.top-1)<<" "; S.top--; } cout<<endl; } } //2 8 16 int main() { int n,k,e; sq_stack S; init_stack(S); cout<<"input number you want to converse:"; cin>>n; cout<<"Hexadecimal number(2,8,16):"; cin>>k; if(k!=2&&k!=8&&k!=16) { cout<<"error"<<endl; return 0; } /* 關於16進位制 10:A 11:B 12:C 13:D 14:E 15:F */ while(n) { int c=n%k; push_stack(S,c); n/=k; } while(!empty_stack(S)) { pop_stack(S,e); if(e>=10) cout<<char(e-10+'A'); else cout<<e; } return 0; } /* int main() { int e; sq_stack S; if(init_stack(S)) { cout<<"Initialization is completed!"<<endl; }else { cout<<"Error"<<endl; return 0; } //入棧: for(int i=1;i<=10;i++) { push_stack(S,i*2); } //長度 cout<<"The length of stack: "<<length_stack(S)<<endl; //得到棧頂元素 if(get_top(S,e)) { cout<<"The top of element: "<<e<<endl; }else cout<<"Error"<<endl; //出棧 //cout<<"out: "<<endl; //while(pop_stack(S,e)) //{ // cout<<e<<" "; //} //cout<<endl; //遍歷棧裡面的元素: cout<<"traverse: "; traverse_stack(S); //再次得到棧頂元素 (從這點可以知道,traverse_stack 並沒有對棧中元素 做出棧 操作,只是指標在動,資料並沒有消失) if(get_top(S,e)) { cout<<"The top of element: "<<e<<endl; } else cout<<"Error"<<endl; //入棧 //cout<<"Input an element you want to insert: "; int flag=1; while(flag) { cout<<"Input an element you want to insert: "; char c; cin>>e; push_stack(S,e); traverse_stack(S); cout<<"continue pushing??? (Y or N)"<<endl; cin>>c; if(c=='Y'||c=='y') flag=1; else flag=0; } //出棧 int flag1=1; cout<<"out: "; while(flag1) { char c; if(pop_stack(S,e)) { cout<<e<<endl<<endl; } cout<<"continue outing??? (Y or N)"<<endl; cin>>c; if(c=='Y'||c=='y') flag1=1; else flag1=0; } //清空 if(clear_stack(S)) { //traverse_stack(S); // 判斷是否為空 if(empty_stack(S)) cout<<"Emptying is done!"<<endl; else cout<<"error"<<endl; }else cout<<"error"<<endl; //銷燬 if(destory_stack(S)) { cout<<"destory finished!"<<endl; } return 0; } */
棧的應用舉例:括號匹配(超經典的~~)
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdlib>
#define ll long long
#define stack_size 100
#define stackincrement 10
#define Selemtype char
#define Status int
#define False 0
#define OK 1
using namespace std;
typedef struct
{
Selemtype *base;//在棧構造之前和毀滅之後 base 的值為 null
Selemtype *top;//棧頂指標(非空棧中的棧頂指標始終在棧頂元素的下一個位置)
int stacksize;//當前已經分配的儲存空間
}sq_stack;
//!!!!!! base top 可是兩個指標啊 !!!!!
//初始化
Status init_stack(sq_stack &S)
{
S.base=(Selemtype *)malloc(stack_size*sizeof(Selemtype));
if(!S.base) return False;
S.top=S.base;
S.stacksize=stack_size;
}
//銷燬 棧 S
Status destory_stack(sq_stack &S)
{
//if(S.base)
//{
// S.base=NULL;
// return OK;
//}
S.top==S.base;
free(S.base);//注意!釋放的不是指標,而是指標指向的空間記憶體~~~~
S.base=NULL;//然後指標指向空
S.top=NULL;
return OK;
}
//置為空棧
Status clear_stack(sq_stack &S)
{
S.top=S.base;
S.stacksize=0;
return OK;
}
//判斷是否為空棧
Status empty_stack(sq_stack S)
{
if(S.base==S.top) return OK;
else return False;
}
//棧的長度
Status length_stack(sq_stack S)
{
if(S.base==NULL||S.base==S.top) return False;
else
return (S.top-S.base);
}
//pop 出棧
Status pop_stack(sq_stack &S,Selemtype &e)
{
if(empty_stack(S)) return False;
S.top--;
e=*(S.top);
return OK;
}
//push 入棧 e入棧
Status push_stack(sq_stack &S,Selemtype e)
{
if(S.top-S.base>=S.stacksize)//空間不夠 要拓展空間
{
S.base=(Selemtype *)malloc((S.stacksize+stackincrement)*sizeof(Selemtype));
if(!S.base) return False;
S.top=S.base+S.stacksize;
S.stacksize+=stackincrement;
}
*S.top=e;
S.top++;
return OK;
}
//get.top 操作
Status get_top(sq_stack S,Selemtype &e)
{
if(empty_stack(S)) return False;
e=*(S.top-1);
return OK;
}
//從棧底到棧頂依次 輸出每個元素
void traverse_stack(sq_stack S)
{
if(empty_stack(S)) cout<<"Error"<<endl;
else
{
while(S.top!=S.base)
{
cout<<*(S.top-1)<<" ";
S.top--;
}
cout<<endl;
}
}
int main()
{
/*輸入一堆括號(“[] () 兩種”),判斷是否匹配 如果匹配的話 最後判斷 棧是不是空 如果是 輸出yes 否則 no*/
/*括號匹配思路:
如果是[ ( 這種的話直接進棧,如果是 ) ] 的話 與 棧頂元素 看是否匹配
如果是的話 棧頂元素出棧 否則 與之匹配的 括號也要進棧 */
sq_stack S;
init_stack(S);
char s[100]={0},e;
int len;
cin>>s;//輸入括號
len=strlen(s);//括號的長度
if(len%2)//如果是奇數的話肯定就不能匹配了~~~
{
cout<<"NO"<<endl;
return 0;
}
//迴圈進棧出棧
for(int i=0;i<len;i++)
{
if(s[i]=='('||s[i]=='[')
{
push_stack(S,s[i]);
continue;
}
if(s[i]==']')
{
if(get_top(S,e))//如果棧頂元素存在的話,就進行匹配 不然入棧
{
if(e=='[')
{
pop_stack(S,e);//匹配了 可以出棧了~~~~
}else push_stack(S,s[i]);
}else push_stack(S,s[i]);
}
if(s[i]==')')
{
if(get_top(S,e))//同理
{
if(e=='(')
{
pop_stack(S,e);//匹配了 可以出棧了~~~~
}else push_stack(S,s[i]);
}else push_stack(S,s[i]);
}
}
if(empty_stack(S))
{
cout<<"YES"<<endl;
}else cout<<"NO"<<endl;
return 0;
}
棧的應用舉例:表示式求值 注意:計算的數字不能是兩位數以上的,而且表示式輸入以後要以‘#’結尾 ,可以看出此程式碼還是很有侷限性的。。。。。哎~~~
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdlib>
#define ll long long
#define stack_size 100
#define stackincrement 10
#define Selemtype char
#define Status int
#define False 0
#define OK 1
using namespace std;
typedef struct
{
Selemtype *base;//在棧構造之前和毀滅之後 base 的值為 null
Selemtype *top;//棧頂指標(非空棧中的棧頂指標始終在棧頂元素的下一個位置)
int stacksize;//當前已經分配的儲存空間
}sq_stack;
//!!!!!! base top 可是兩個指標啊 !!!!!
//初始化
Status init_stack(sq_stack &S)
{
S.base=(Selemtype *)malloc(stack_size*sizeof(Selemtype));
if(!S.base) return False;
S.top=S.base;
S.stacksize=stack_size;
}
//銷燬 棧 S
Status destory_stack(sq_stack &S)
{
//if(S.base)
//{
// S.base=NULL;
// return OK;
//}
S.top==S.base;
free(S.base);//注意!釋放的不是指標,而是指標指向的空間記憶體~~~~
S.base=NULL;//然後指標指向空
S.top=NULL;
return OK;
}
//置為空棧
Status clear_stack(sq_stack &S)
{
S.top=S.base;
S.stacksize=0;
return OK;
}
//判斷是否為空棧
Status empty_stack(sq_stack S)
{
if(S.base==S.top) return OK;
else return False;
}
//棧的長度
Status length_stack(sq_stack S)
{
if(S.base==NULL||S.base==S.top) return False;
else
return (S.top-S.base);
}
//pop 出棧
Status pop_stack(sq_stack &S,Selemtype &e)
{
if(empty_stack(S)) return False;
S.top--;
e=*(S.top);
return OK;
}
//push 入棧 e入棧
Status push_stack(sq_stack &S,Selemtype e)
{
if(S.top-S.base>=S.stacksize)//空間不夠 要拓展空間
{
S.base=(Selemtype *)malloc((S.stacksize+stackincrement)*sizeof(Selemtype));
if(!S.base) return False;
S.top=S.base+S.stacksize;
S.stacksize+=stackincrement;
}
*S.top=e;
S.top++;
return OK;
}
//get.top 操作
Selemtype get_top(sq_stack S)
{
if(empty_stack(S)) return False;
return (*(S.top-1));
}
//從棧底到棧頂依次 輸出每個元素
void traverse_stack(sq_stack S)
{
if(empty_stack(S)) cout<<"Error"<<endl;
else
{
while(S.top!=S.base)
{
cout<<*(S.top-1)<<" ";
S.top--;
}
cout<<endl;
}
}
int in(Selemtype c)
{
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'#':return 1;
default:return 0;
}
}
//運算
char operate_stack(int a,char op,int b)
{
switch(op)
{
case '+': return (char)(a+b+'0');
case '-': return (char)(a-b+'0');
case '*': return (char)(a*b+'0');
case '/': return (char)(a/b+'0');
default: return '0';
}
}
//運算子比較
int compare_stack(char op1,char op2)//大的返回 3 小的 返回 2 等於 返回 1 錯誤 返回 0
{
if(op1=='+')
{
if((op2=='+')||(op2=='-')||(op2==')')||(op2=='#'))
return 3;
else return 2;
}
else if(op1=='-')
{
if((op2=='+')||(op2=='-')||(op2==')')||(op2=='#'))
{
return 3;
}else return 2;
}
else if(op1=='*')
{
if(op2=='(')
return 2;
else return 3;
}
else if(op1=='/')
{
if(op2=='(')
return 2;
else return 3;
}
else if(op1=='(')
{
if(op2==')')
return 1;
else if((op2=='+')||(op2=='-')||(op2=='*')||(op2=='/')||(op2=='('))
return 2;
}
else if(op1==')')
{
if(op2!='(')
return 3;
}
else if(op1=='#')
{
if(op2=='#')
return 1;
else if((op2=='+')||(op2=='-')||(op2=='*')||(op2=='/')||(op2=='('))
return 2;
}
return 0;
}
//運算子比較相等的話 入棧
int main()
{
//如果是數字就入棧 如果是運算子 就跟 棧頂元素 作比較 如果高的話就進棧,否則運算
sq_stack S_optr,S_opnd;//兩個棧 一個是運算子棧一個是運算數棧 char型別
char c;
Selemtype e,a,b;
init_stack(S_optr);
init_stack(S_opnd);
push_stack(S_optr,'#'); //最低階的#入運算子棧
cout<<"input ( End with '#' ): ";
c=getchar();//注意一個字元一個字元的輸入;
int cnt=0;
while(c!='#'||get_top(S_optr)!='#')
{
if(c>='0'&&c<='9') {
push_stack(S_opnd,c);
c=getchar();//不要忘了 繼續下一個字元的輸入,結束按回車
}
else
{//新輸入的字元與 運算子棧頂 元素 比較 優先順序, 高的 入棧 低的 棧頂元素出棧,進行運算
if(!in(c))//判斷是不是合法字元
{
cout<<"error"<<endl;
return 0;
}
int op=compare_stack(get_top(S_optr),c);
// cout<<op<<endl;
switch(op)
{
case 2: //棧頂元素低,字元進棧, 2 <---> '<'
push_stack(S_optr,c);
// cout<<"case 2:optr ";traverse_stack(S_optr);
// cout<<"case 2:opnd ";traverse_stack(S_opnd);
c=getchar();//繼續輸入
break;
case 1://棧頂元素相等 1 <---> '='
pop_stack(S_optr,e);// 運算子規則裡,()相等 所以脫括號 出棧
// cout<<"case 1 optr "; traverse_stack(S_optr);
// cout<<"case 1 opnd ";traverse_stack(S_opnd);
c=getchar();
break;
case 3://棧頂元素優先順序高,出棧, 運算數 出棧兩個哦 3 <--> '='
pop_stack(S_optr,e);
pop_stack(S_opnd,b);
pop_stack(S_opnd,a);//b比a先出
push_stack(S_opnd,operate_stack((int)a-'0',e,(int)b-'0'));
break;
}
}
}
// traverse_stack(S_opnd);
// traverse_stack(S_optr);
char ans=get_top(S_opnd);
if(ans>='0'&&ans<='9')
cout<<ans<<endl;
else cout<<int(ans-'0')<<endl;
return 0;
}