数据结构归纳——队列和堆栈

队列和堆栈分顺序和链式队列和堆栈,我感觉没什么好归纳的,不难。队列先入先出,堆栈先入后出。队列还有循环队列。和堆排序结合后还有优先队列(实际应用比较多)。还有一些经典的应用,如中缀转后缀,后缀的计算等用到了堆栈,然后二叉树的一些遍历也经常用到队列和堆栈。简单的说都是对顺序储存结构(比如说数组)和链式储存结构(比如说链表)进行了一次封装,然后给了这些储存结构一些新的性质。最后还是那句话,只要思路掌握了,具体实现大可以写出水平写出风格!

一,队列:

template <class T>
class Queue
{
protected:
	int front,rear;	         
		T  *data;	         
	int maxsize;	         
public:
	Queue ( int sz = 10 ){
		rear= front=0;
		maxsize=sz;
		data=new T[maxsize];
	};        
	~Queue ( ) { 
		delete [ ] data; 
	}
	void Enq ( T & item );    
	int Outq( T & item);            
	void MakeEmpty ( );    
	int IsEmpty ( );
	int IsFull ( );
};
template <class T>
void Queue<T>::Enq( T & item )
{
	assert ( !IsFull ( ) );	       //先决条件断言
	data[ rear] = item;     //加入新元素
	rear++;
}
template <class T>
int  Queue<T>::Outq( T & item)
{
	if ( IsEmpty ( ) ) return 0;  //
	item=data[front];
	front++;
	return 1;    

}
template <class T>
int  Queue<T>::IsEmpty ( )
{
	if (front==rear)
	{
		return 1;
	} 
	else
	{
		return 0;
	}
}
template <class T>
int  Queue<T>::IsFull( )
{
	if (rear==maxsize)
	{
		return 1;
	} 
	else
	{
		return 0;
	}
}
template <class T>
void  Queue<T>::MakeEmpty()
{
	rear=front=0;
}

二,堆栈:

class Stack
{
protected:
	int top;	                   //栈顶指针
	Type *elements;	            //栈元素数组
	int maxSize;	                  //栈最大容量
public:
	Stack ( int sz = 10 );            //构造函数
	~Stack ( ) { delete [ ] elements; }
	void Push ( Type & item );         //进栈
	int Pop( Type & item);            //出栈
	Type GetTop ( );                    //取栈顶
	void MakeEmpty ( ) { top = -1; }       //置空栈
	int IsEmpty ( ) const { return top == -1; }
	int IsFull ( ) const
	{ return top == maxSize-1; }
};


template <class Type>
Stack<Type> ::Stack ( int s ) : top (-1), maxSize (s)
{
	elements = new Type[maxSize];
	assert ( elements != NULL );        //断言
}


template <class Type>
void Stack<Type> ::Push ( Type & item )
{
	assert ( !IsFull ( ) );	       //先决条件断言
	elements[++top] = item;     //加入新元素
} ;

template <class Type>
int Stack<Type> ::Pop (Type &Item )
{
	if ( IsEmpty ( ) ) return 0;  //栈空不退栈
	Item=elements[top];
	top--;
	return 1;                //退出栈顶元素
}


template <class Type>
Type Stack<Type>::GetTop ( )
{
	assert ( !IsEmpty ( ) );	     //先决条件断言
	return elements[top];         //取出栈顶元素
}

三,堆栈的应用——中缀转后缀并计算

//具体规则为:在中序序列中遇到数值,直接放到后缀序列中遇到“(”入栈,遇到比“)”出栈直到和他相对应的“(”,
//并将“(”也出栈,
//把除括号外的运算符放后缀到序列中。对于其他运算符,
//遇到比栈顶元素大的运算符入栈,遇到比栈顶元素小的,将栈顶元素出栈,直到栈顶运算符比当前运算符优先级小,并将当
//前运算符入栈,直到中缀序列结束。最后将栈内运算符放到后缀序列中。
void operation(char* exp1)//中缀转后缀
{
	int i=0;
	int pos1=0,pos2=0;
	char *exp2;
	exp2=new char[100];
	char temp;
	Stack<char> s2(100);//通过栈正确输出运算符顺序
	char first='#';
	s2.Push(first);
	while(exp1[pos1]!='#')
	{
		if(judgenum(exp1[pos1]))
		{
			exp2[pos2]=exp1[pos1];
			pos2++;
			pos1++;
		}
		else
		{
			char sign=judgeop(s2.GetTop(),exp1[pos1]);
			switch(sign)
			{
			case '>':s2.Push(exp1[pos1]),pos1++;break;
			case '=':s2.Pop(temp),pos1++;break;
			case '<':
				{
					s2.Pop(temp);
					exp2[pos2]=temp;
					pos2++;
					break;
				}
			}
		}
	}
	while(s2.Pop(temp))
	{
		exp2[pos2]=temp;
		pos2++;
	}
	cout<<"后缀表达式为:";
	while(exp2[i]!='#')
	{
		cout<<exp2[i]<<" ";
		i++;

	}
	cout<<endl;
	cout<<"结果为:";
	Result(exp2);
	cout<<endl;
	delete[]exp2;
}
char judgeop(char o1,char o2)//优先级比较
{
	switch(o1)
	{
	case '#':return '>';
	case '+':{switch(o2)
			 {
				case '*':
				case '/':
				case '(':return '>';
				case '+':
				case '-':
				case ')':return '<';
			 }}
	case '-':
		{
			switch(o2)
			{

			case '*':
			case '/':
			case '(':return '>';
			case '+':
			case '-':
			case ')':return '<';
			}
		}
	case '*':
		{
			switch(o2)
			{
			case '(':return '>';
			case '*':
			case '/':
			case '-':
			case '+':
			case ')':return '<';
			}
		}
	case '/':
		{
			switch(o2)
			{	
			case '(':return '>';
			case '*':
			case '/':
			case '+':
			case '-':
			case ')':return '<';
			}
		}
	case '(':
		{
			switch(o2)
			{
			case '+':
			case '-':
			case '*':
			case '/':
			case '(':return '>';
			case ')':return '=';
			}
		}

	}
}
double operate(double a,double b,char c)//单个运算符的计算
{
	switch(c)
	{
	case '+':return (a+b);
	case '-':return (a-b);
	case '*':return (a*b);
	case '/':return (a/b);
	}
}


//将后序序列中元素入栈,当遇到运算符时出栈两个元素和运算符进行运算,将结果入栈,如此连续
//到序列运算完成,,,,
void Result(char *exp1)//计算后缀表达式
{
	Stack<double> s1(100);
	int pos=0;
	double temp1,temp2;
	double result=0;

	while(exp1[pos]!='#')
	{
		if (exp1[pos]>=48&&exp1[pos]<=57)
		{
			double d=(double)(exp1[pos]-48);
			s1.Push(d);
			pos++;
		} 
		else
		{
			s1.Pop(temp1);
			s1.Pop(temp2);
			result=operate(temp2,temp1,exp1[pos]);
			s1.Push(result);
			pos++;
		}
	}
	s1.Pop(result);
	cout<<result<<endl;
}


四,队列的应用:

//队列的应用:根据关系划分子集,
void divisition(int r[9][9],int n)
{
	int *q,*temp,*s;
	q=new int[n];
	temp=new int[n];
	s=new int[n];
	Queue<int> que(20);
	int set=0,i,k,per=1;
	for (k=1;k<=n;k++)//第一次将所有元素入队
	{
		que.Enq(k);
	}
	do 
	{
		que.Outq(i);
		if (i<=per)//如果当前值比前一个小的话说明一个子集排完,开始排下一个子集
		{
			set++;//子集数加一
			s[i]=set;
			for(k=1;k<=n;k++)
				temp[k]=r[i][k];
			per=i;
		}
		else
		{
			if (temp[i]!=0)//冲突,重新入队,等待下一次排列
			{
				que.Enq(i);
			} 
			else
			{
				s[i]=set;//不冲突,赋值为当前子集数
				for (k=i+1;k<=n;k++)
				{
					temp[k]=temp[k]+r[i][k];//增加当前值的冲突关系
				}
			}
			per=i;//标记当前值,和下一个比较
		}
	} while (!que.IsEmpty());
	cout<<"元素    :";
	for(int i=1;i<=9;i++)
		cout<<i<<" ";
	cout<<endl;
	cout<<"所属子集:";
	for(int i=1;i<=n;i++)
		cout<<s[i]<<" ";
	delete []q;
	delete []s;
	delete []temp;

}



 







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值