第三章 栈和队列

一、栈

逻辑结构:同线性表-一对一

存储结构:顺序栈和链栈均可,顺序栈常见

只能栈顶运算,先入后出原则

//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.队列应用

汽车加油

打印机缓冲区





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