第三章 棧和隊列

一、棧

邏輯結構:同線性表-一對一

存儲結構:順序棧和鏈棧均可,順序棧常見

只能棧頂運算,先入後出原則

//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;

         }

}

遞歸適用樹,廣義表

時間效率O2^n),與遞歸樹的結點數成正比

空間效率On),與遞歸樹的深度成正比

 

三、隊列

先進先出

順序表示-一維數組

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.隊列應用

汽車加油

打印機緩衝區





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章