一、棧
邏輯結構:同線性表-一對一
存儲結構:順序棧和鏈棧均可,順序棧常見
只能棧頂運算,先入後出原則
//SElemType 可替換爲int等數據類型
//1.構造順序棧
struct SqStack
{
SElemType *top;
SElemType *base;
int stacksize;
};
//2.順序棧的初始化
Status InitStack(SqStack &s)
{
s.base=new SElemType [MAXSIZE];
if(!s.base)
exit(OVERFLOW);
s.top=s.base;
s.stacksize=MAXSIZE;
return Ok;
}
//3.判斷順序棧是否爲空
bool StackEmpty(SqStack s)
{
if(s.top==s.base)
return true;
else
return false;
}
//4.清空
void ClearStack(SqStack &s)
{
if(s.base)
s.top=s.base;
}
//5.銷燬
void DestroyStack(SqStack &s)
{
if(s.base)
{
delete s.base;
s.stacksize=0;
s.base=s.top=NULL;
}
}
//6.順序棧進棧
void Push(SqStack &s,SElemType e)
{
if(s.top-s.base!=s.stacksize)//top-base不能棧滿
{
*s.top=e;
s.top++;
//*s.top++=e;
}
}
//7.順序棧出棧
void Pop(SqStack &s,SElemType &e)
{
if(s.top!=s.base) //不能棧空
{
--s.top;
e=*s.top;
//e=*--s.top;
}
}
//8.取順序棧棧頂元素
void GetTop(SqStack s,SElemType &e)
{
if(s.base!=s.top)
e=*(s.top-1);
}
2.鏈棧
#include <iostream>
using namespace std;
#define MAXSIZE 100
//1.構造鏈棧
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
//2.初始化鏈棧 s->^ 即可
void InitLinkStack(LinkStack &s)
{
s=NULL;
}
//3.判斷鏈棧是否爲空
bool IsEmptyLStack(LinkStack s)
{
if(s==NULL)
return true;
else
return false;
}
//4.進棧,將p放在首位
void PushLStack(LinkStack &s,ElemType e)
{
LinkStack p;
p=new StackNode;
if(!p)
exit(OVERFLOW);//溢出用exit()函數
p->data=e;
p->next=s;
s=p;
}
//5.出棧
void PopLStack(LinkStack &s,ElemType &e)
{
if(s)//要保證s不爲空
{
e=s->data;
LinkStack p;
p=s;
s=s->next;
delete p;
}
}
//6.取棧頂元素
SElemType GetTop(LinkStack s)
{
if(s==NULL)
exit(1);
return s->data;
}
二、棧的應用
1.數制轉換(十進制轉N進制)用棧暫存低位值
#include <iostream>
using namespace std;
#define num 8//表示轉化爲8進制
void conversion()
{
int n;
InitStack(s);
cin>>n;
while(n)
{
push(s,n%num);
n=n/num;
}
while(!stackEmpty(s))//棧非空時彈出
{
pop(s,e);
cout<<e;
}
}
2.括號匹配的檢驗(用棧暫存左括號)
可運行-轉載
#include <iostream>
#include <string>
using namespace std;
#define maxsize 100
struct sStack
{
char sign[maxsize];
int top;
};
int InitsStack(sStack &SS)
{
SS.top=-1;
return 1;
}
int IsEmptysStack(sStack &SS)
{
if(SS.top==-1)
return 1;
return 0;
}
int PushsStack(sStack &SS,char c)
{
SS.sign[++SS.top]=c;
return 1;
}
int UpsStack(sStack &SS)
{
if(IsEmptysStack(SS))
{
cout<<"棧空"<<endl;
return 0;
}
SS.top--;
return 1;
}
char TopsStack(sStack &SS)
{
if(IsEmptysStack (SS))
{
cout <<"棧空"<<endl;
return 0;
}
return SS.sign[SS.top];
}
int main()
{
string s;
cout<<"輸入表達式:";
cin>>s;
int length=s.length();
int i;
sStack SS;
InitsStack(SS);
for(i=0;i<length;++i)
{
if(s[i]=='('||s[i]=='['||s[i]=='{')
PushsStack(SS,s[i]);
else if(s[i]==')'&&!IsEmptysStack(SS)&&TopsStack(SS)=='(')
UpsStack(SS);
else if(s[i]==')'&&!IsEmptysStack(SS)&&TopsStack(SS)!='(')
cout<<"括號匹配次序不正確"<<endl;
else if(s[i]==']'&&!IsEmptysStack(SS)&&TopsStack(SS)=='[')
UpsStack(SS);
else if(s[i]==']'&&!IsEmptysStack(SS)&&TopsStack(SS)!='[')
cout<<"括號匹配次序不正確"<<endl;
else if(s[i]=='}'&&!IsEmptysStack(SS)&&TopsStack(SS)=='{')
UpsStack(SS);
else if(s[i]=='}'&&!IsEmptysStack(SS)&&TopsStack(SS)!='{')
cout<<"括號匹配次序不正確"<<endl;
else if((s[i]==')'||s[i]==']'||s[i]=='}')&&IsEmptysStack(SS))
cout<<"右括號多於左括號"<<endl;
}
if(!IsEmptysStack(SS))
cout<<"左括號多於右括號"<<endl;
else if(i=(length-1)&&IsEmptysStack(SS))
cout<<"括號匹配正確"<<endl;
system("PAUSE");
return 0;
}
3.表達式求值(用棧暫存運算符)
算法思想如下:#include <iostream>
#include <stack>
using namespace std;
void main()
{
stack<char> s;
char c,x;
int flag=1;
cin>>c;
while(c!='#'&&flag)
{
switch(c)
{
case '['||'(':
s.push(c);
break;
case ')':
x=s.top();
if(x=='(')
s.pop();
else
flag=0;
break;
case ']':
x=s.top();
if(x=='[')
s.pop();
else
flag=0;
break;
}
cin>>c;
}
}
轉載:任意表達式求值-方法
http://blog.csdn.net/flyfy1/article/details/5309551
4.迷宮求解(用棧實現遞歸調用)
“分治法”求解遞歸問題
void p(參數)
{
If(遞歸結束條件成立)
可直接求解;
elsep(較小或較大的參數);//遞歸步驟
}
遞歸解決的問題:
1) n階乘
fact(n)={1若n=0; n*fact(n-1);若n>0}
2) 斐波那契
Fib(n)={1 若n=1,2; fib(n-1)+fib(n-2) 其他}
3) 漢諾塔
把n-1個盤子從A移到B,把最下面的移到C;
把n-2個盤子從B移到A,第n-1個移到C,如此反覆
4) 迷宮
5) 轉二進制
void conversion(int n)
{
if(n==1)
cout<<n%2;
else
{
conversion(n/2);
cout<<n%2;
}
}
遞歸適用樹,廣義表
時間效率O(2^n),與遞歸樹的結點數成正比
空間效率O(n),與遞歸樹的深度成正比
三、隊列
先進先出
順序表示-一維數組
1.循環隊列
#include <iostream>
using namespace std;
#define MAXQSIZE 100//最大隊列長度
//1.構造循環隊列
struct SqQueue
{
QElemType *base;
int front;//頭指針,指向對頭元素
int rear;//尾指針,指向隊尾元素的下一個位置
};
//2.初始化
void InitQueue(SqQueue &q)
{
q.base=new QElemType[MAXQSIZE];
if(!q.base)
exit(OVERFLOW);
q.front=q.rear=0;
}
//3.求循環對列長度
int QueueLength(SqQueue q)
{
return (q.rear-q.front+MAXQSIZE)%MAXQSIZE;
}
//4.入隊列
void EnQueue(SqQueue &q,QElemType e)
{
if((q.rear+1)%MAXQSIZE!=q.front)
{
q.base[q.rear]=e;
q.rear=(q.rear+1)%MAXQSIZE;
}
}
//5.出隊列
void DeQueue(SqQueue &q,QElemType e)
{
if(q.front!=q.rear)
{
e=q.base[q.front];
q.front=(q.front+1)%MAXQSIZE;
}
}
2.鏈隊列
#include <iostream>
using namespace std;
//1.構造鏈隊列
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;//隊頭指針
QueuePtr rear;//對尾指針
}LinkQueue;
//2.初始化
void InitQueue(LinkQueue &q)
{
q.front=q.rear=(QueuePtr)malloc(sizeof(QNode));//malloc動態分配(大小)的內存
if(!q.front)
exit(OVERFLOW);
q.front-next=NULL;
}
//3.銷燬隊列
void DestroyQueue(LinkQueue &q)
{
while(q.front)
{
q.rear=q.front->next;
free(q.front);
q.front=q.rear;
}
}
//4,判斷是否爲空
bool EmptyQueue(LinkQueue q)
{
if(q.front==q.rear)
return true;
else
return false;
}
//5.求鏈隊列的頭元素
void GetHead(LinkQueue q,QElemType &e)
{
if(q.front!=q.rear)
e=q.front->next->data;
}
//6.鏈隊列入隊
void EnQueue(LinkQueue &q,QElemType e)
{
LinkQueue p;
p=(QueuePtr)malloc(sizeof(QNode));
if(!p)
exit(OVERFLOW);
p->data=e;
p->next=NULL;
q.rear->next=p;
q.rear=p;//修改隊尾指針
}
//7.鏈隊列出隊
void DeQueue(LinkQueue &q,QElemType &e)
{
LinkQueue p=(QueuePtr)malloc(sizeof(QNode));
if(q.front!=q.rear)
{
p=q.front->next;
e=p->data;
q.front->next=p->next;
if(q.rear==p)
q.rear=q.front;
delete p;
}
}
3.隊列應用
汽車加油
打印機緩衝區