您的位置:首页 > 理论基础 > 数据结构算法

数据结构--栈和队列

2014-04-10 16:57 531 查看

栈和队列

1. 栈

只在表的一端访问元素的表,其元素只能从栈顶端增加或删除。设计存放那些只能从一端访问的元素。

增加(压入push):栈顶增加元素

和删除(弹出pop):栈顶删除元素

后进先出原则(LIFO)

栈满:栈已达到处理元素个数的最大值。 栈空:无法从栈中删除元素。

2.类Stack

数组存放栈元素。栈对象说明包括栈大小,定义表中最多能存放的元素个数(默认值MaxStackSize=50)

Stack:Size(栈大小)和下标top都是类Stack的私有成员。

初始化时栈为空,top=-1。每压入一个,top+1(0,1,2,...);每弹出一个,top-1(...2,1,0)

class Stack

{

private:

DataType stacklist[MaxStackSize];

int top; //指针

public:

Stack(void);//构造函数 -〉Stack::Stack(void):top(-1)

void Push(const DataType& item); //if(top==MaxStackSize-1) cout<<"StackOverflow"<<endl;exit(l);top++;stacklist[top]=item;

DataType Pop(void);//if(top==-1) cout<<"StackEmpty"<<endl;exit(l);temp=stackList[top];top--;return temp;

void ClearStack(void); //赋值top=-1 清空栈,可移作他用

DataType peek(void) const; //访问栈顶元素 ,等同于pop,但不将top-1,保持栈的状态不变。

int StackEmpty(void) const; //检测是否栈空,是否可进行pop操作 return top==-1

int StackFull(void) const; //检测是否栈满,用数组实现,是否可进行push操作 return top=MaxStackSize-1

}

栈的实现:

typedef int DataType;

#include "astack.h"

Stack s;

s.Push(10);

cout<<s.Peek()<<endl;

if(!StackEmpty())

temp=s.Pop();

cout<<temp<<endl;

s.ClearStack(); //清空栈操作

注意:栈可以以多进制(非十进制)输出数据:

void MultibaseOutput(long num,int B)

{

Stack S;

do{ S.Push(num % B);

num/=B; }while(num!=0)

while(!S.StackEmpty()){ cout<<S.Pop();}

}

3.表达式求值

中缀表达式:4+3*5 的后缀表达式:435*+,求值步骤:

a.读入操作数:435并将每个数压入栈中

b.读入操作符:* 并通过弹出操作数5和3来计算3*5,将结果15压回栈中

c.读入操作符:+ 并通过弹出操作数15和4来计算15+4,将结果19压回栈中,即是表达式的最后结果。

[举例]计算器功能的实现:

enum Boolean(False,True);

typedef double DataType;

#include "astack.h"

class Calculator{

private:

Stack s;//存放操作数的栈

void Enter(double num);

Boolean GetTwoOperands(double& opnd1,double& opnd2);//是否得到了2个操作数

void Compute(char op); //通过操作符计算

public:

Calculator(void); //构造函数

void Run(void);//计算表达式值

void Clear(void);//清空计算器

};

实现功能:(类定义文件calc.h)

void Calculator::Enter(double num)

{ S.Push(num);

}

Boolean Calculator::GetTwoOperands(double& opnd1,double& opnd2)

{ if(S.StackEmpty()){cerr<<"Missing operand!"<<endl;return False;}

opnd1 =S.Pop();//取右操作数

if(S.StackEmpty()){cerr<<"Missing operand!"<<endl;return False;}

opnd2 =S.Pop();//取左操作数

return True;

}

void Calculator::Compute(char op)

{ Boolean result;

double operand1,operand2;

result=GetTwoOperands(operand1,operand2);

if(result==True)

{ switch(op)

{

case '+':S.Push(operand2+operand1);break;

case '-':S.Push(operand2-operand1);break;

case '*':S.Push(operand2*operand1);break;

case '/': if(operand1=0.0){cerr<<"Divide by 0 err!"<<endl;S.ClearStack();}

else S.Push(operand2/operand1);break;

case '^':S.Push(pow(operand2,operand1));break; //乘方运算

}

}

else S.ClearStack();

}

void Calculator::Run(void)

{

char c;

double newoperand;

while(cin>>c,c!='=')

{ switch(c)

{

case '+':

case '-':

case '*':

case '/':

case '^': Compute(c);break; //读到运算求值。

defualt: cin.putback(c);//非运算符必为操作数,将字符送回

cin>>newoperand;

Enter(newoperand);

break; //读入操作并将其存入栈中

}

}

if(!S.StackEmpty())

cout<<S.Peek()<<endl;

}

void Calculator::Clear(void)

{

S.ClearStack();

}

4.队列

队列是以表形式存放元素,但只允许在表的两端访问元素的数据结构。队列中的元素在表尾插入,在表头删除。应用中按出现顺序存放元素。

先进先出原则(FIFO),举例顾客排队,烤羊肉串等。

队列由表以及指定的对表头和表尾位置元素的访问操作组成。这2个位置分别插入和删除队列中的元素。如果用数组来实现表,有可能出现“队列满”的情况。

5.类Queue

类Queue 用数组存放表中的元素,并定义变量来指定表头和表尾位置,以实现Queue.此外还定义了QFull来检测数组是否已满。

#include <iostream.h>

#include <stdlib.h>

const int MaxQSize=0;

class Queue

{ private:

int front,rear,count; //队列数组及其参数

DataType qlist[MaxQSize];

public:

Queue(void);//构造函数

void QInsert(const DataType& item);//队列元素插入(表尾)

DataType QDelete(void);//队列元素删除(表头)

void ClearQueue(void);//清空队列

DataType QFront(void) const; //访问队列

int QLength(void) const; //队列中元素个数

int QFull(void) const; //队列是否满

int QEmpty(void) const; //队列是否空

};

typedef int DataType;

#include "aqueue.h"

Queue Q; //定义队列对象Q

Q.QInsert(10); //表尾处插入元素10

Q.QInsert(7); //表尾处再插入元素7

cout<<Q.QLength()<<endl; //打印队列中元素个数为2个

cout<<Q.QFront()<<endl;// 打印结果为10

if(!Q.QEmpty())

{

cout<<Q.QDelete()<<endl; //表头删除元素并返回删除元素10

}

cout<<Q.QFont()<<endl; //删除后返回表头元素7

Q.ClearQueue(); //清空队列

队列实现方法:环状队列(求余算法)

rear指针前移:rear=(rear+1)%MaxQSize;

front指针前移:front=(front+1)%MaxQSize;





Queue构造函数:Queue::Queue(void):front(0),rear(0),count(0);//初始化一个空队列

队列操作:(1)队列插入 Queue::QInsert(const DataType& item)

{ //如果队列已满,则出错退出

if(count ==MaxQSize){cerr<<"Queue overflow!"<<endl;exit(l);}

count++;

qlist[rear]=item;

rear=(rear+1)%MaxQSize;

}

(2)队列删除 DataType Queue::QDelete(void)

{ DataType temp;

//如果队列已空,则出错退出

if(count ==0){cerr<<"Deleting from an empty Queue !"<<endl;exit(l);}

temp=qlist[front];

count--;

front=(font+1)%MaxQSize;

return temp;

}

6.优先级队列

实际应用中,删除优先级最高的元素,即优先级队列。PQInsert()简单的将元素插入到队列中,

PQDelete()则根据某些外部因素来判断元素的重要程度,并删除优先级最高的元素。

即替换原来先来先处理的事务处理机制(队列),根据事务重要程度来处理他们(优先级队列)

举例在操作系统中,进程任务优先级数值小的优先级大。大多数应用,优先级队列是一对权值对。

即 “优先级-任务描述符”。如果存在多个优先级相同的元素,那么按正常的到达先后的顺序进行服务。

优先级队列类:PQueue类

#include <iostream.h>

#include <stdlib.h>

const int MaxPQSize=50;

class PQueue

{

private:

int count;

DataType pqlist[MaxPQSize];

public:

PQueue(void);

void PQInsert(const DataType& item);

DataType PQDelete(void); //与QDelete不同的是,它删除优先级最高的元素。如果优先级最高的元素是值最小的元素,最小值定义为"〈"符号。

void ClearPQ(void);

int PQEmpty(void) const;

int PQFull(void) const;

int PQLength(void) const;

};

PQueue类的实现:

优先级队列的操作:

(1)插入元素操作PQInsert()

void PQueue::PQInsert(const DataType& item)

{

if(count ==MaxPQSize){cerr<<"Priority Queue overflow!"<<endl;exit(l);}

pqlist[count]==item;

count++;

}

(2)删除优先级最高元素操作PQDelete(),并指定在相同优先级下删除哪个元素

DataType PQueue::PQDelete(void)

{

DataType min; //指定最小值即为优先级最高的元素

int i,minindex=0; //最小值下标minindex

if(count>0) //在队列中有元素的情况下

{

min=pqlist[0];//假定pqlist[0]为最小值

for(i=1;i<count;i++)

{

if(pqlist[i]< min)

{ min=pqlist[i];minindex=i;}

}

pqlist[minindex] =pqlist[count-1]; //将表尾的元素移入最小元素位置

count--;

}

else //在队列为空的情况下,报错退出

{ cerr<<"Deleting from an empty pqueue!"<<endl;exit(l);}

return min; //返回最小值

}

继续补充。。。

分享:




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: