数据结构期中复习---第三章栈和队列---程序片段

第三章 栈和队列

1.顺序栈的实现

const  int  StackSize=100; 
template  <typename DataType> 
class  SeqStack{ 
    private: 
        DataType  data[StackSize]; 
        int  top; 
    public: 
        SeqStack(){top=-1;} 
        ~SeqStack(){} 
        void  push(DataType  x);    //入栈操作,将元素x入栈 
        DataType pop();    //出栈操作 
        DataType  Gettop();    //取栈顶元素 
        int  Empty(){return  top==-1?1:0;}  //判断栈是否为空 
        int  getSize(){return  top;}    //返回栈的长度 
}; 
template<typename DataType> 
void  SeqStack<DataType>::push(DataType  x){ 
	if(top==StackSize-1) cout<<"full";
	data[++top]=x;     //也可能是top++,当top指向最后一个数据元素的下一个位置时
}
template<typename DataType> 
DataType SeqStack<DataType>::pop(){ 
 	DataType x;
 	if(top==-1) cout<<"empty";
 	x=data[top--];
	return x;
} 
template<typename DataType> 
DataType    SeqStack<DataType>::Gettop(){ 
        if(top==-1)  cout<<"empty"; 
        else  return  data[top]; 
} 

2.数制转换(顺序栈)

十进制数N和其他d进制数的转换是计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理:N = (N div d) * d +(N mod d)
其中div是整除运算,mod是求余运算。例如(2018)10= (3742)8= (7E2)16

int main()
{
	int N,d;
	cin>>N>>d;
	SeqStack<int>S;
 	int m;
 	int e; 
 	while(N>0)
 	{
 		m=N%d;
  		N=N/d;
  		S.Push(m);
 	}
 	while(S.Empty()==0)
 	{
 		e=S.Pop();
  		if(e>9) cout<<char(e+55);
  		else cout<<e;
 	}
}

3.括号匹配(顺序栈)

自己想的,有编译信息的错误

int main()
{
 	string str;
 	cin>>str;
 	SeqStack<char>S;
 	int i;
 	for(i=0;i<str.length() ;i++)
 	{
  		if(str[i]=='(' || str[i]=='[' || str[i]=='{')
 		{
   			S.Push(str[i]);
  		}
  		else if(str[i]==')' || str[i]==']' || str[i]=='}') 
  		{
   			if(S.Empty()==1 ) 
   			{
    				cout<<"NO";
    				i++;    
    		//必须有这句,来排除当遍历到最后一个i=str.length()-1时,前面没有匹配的右括号
    				break;
   			}
   			else S.Pop() ;
  		}
 	}
 	if(S.Empty() ==0) cout<<"NO";
 	else if(S.Empty() ==1 && i==str.length()-1) cout<<"YES";
} 

4. 合法序列(顺序栈)和上一个差不多

假设以I和O分别表示入栈和出栈操作,栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。写出一个算法,判定所给的操作序列是否合法。若合法,输出1,否则输出0。

int main()
{
 	string str;
 	cin>>str;
 	int flag;
 	SeqStack<char>S;
 	for(int i=0;i<str.length() ;i++)
 	{
  		if(str[i]=='I')
  		{
   			S.Push(str[i]);
  		}
  		else if(str[i]=='O') 
  		{
   			if(S.Empty() ) flag=0;
   			else S.Pop() ;
  		}
 	}
 	if(S.Empty() ==0) flag=0;
 	else flag=1;
 	cout<<flag;
} 

5.中缀表达式转后缀表达式并求值(顺序栈)

bool  Number(char  ch)//判断是否为数字,是则返回true 
{ 
 	if(ch>='0' && ch<='9') return true;
	else return false;

} 

具体实现代码

#include  <iostream> 
#include  <math.h> 
#include<stdio.h> 
using  namespace  std; 
const  int  StackSize=100; 
template  <class  DataType> 
class  SeqStack{ 
private: 
        DataType  data[StackSize]; 
        int  top; 
public: 
        SeqStack(){top=-1;} 
        ~SeqStack(){} 
        void  push(DataType  x);    //入栈操作,将元素x入栈 
        void  pop();    //出栈操作 
        DataType  Gettop();    //取栈顶元素 
        int  Empty(){return  top==-1?1:0;}  //判断栈是否为空 
        int  getSize(){return  top;}    //返回栈的长度 
}; 
template<class  DataType> 
void  SeqStack<DataType>::push(DataType  x){ 
 	if(top==StackSize-1) cout<<"full";
	data[++top]=x;
} 
template<class  DataType> 
void    SeqStack<DataType>::pop(){ 
 	if(top==-1) cout<<"empty";
	top--;
} 
template<class  DataType> 
DataType    SeqStack<DataType>::Gettop(){ 
        if(top==-1)  cout<<"empty"; 
        else 
                return  data[top]; 
} 
bool  Number(char  ch)//判断是否为数字,是则返回true 
{ 
 	if(ch>='0' && ch<='9') return true;
	else return false;
} 

void  InPut(char*&  str)//接收输入的中缀表达式的函数,并简单判断是否合法 
{ 
        //cout  <<  "Please  Enter  What  You  Want  To  calculation:"  <<  endl; 
        while  (1) 
        { 
                cin  >>  str; 

                if  (Number(str[0]))//中缀表达式的第一个必定是数字,如果不是,则非法 
                { 
                        break; 
                } 
                else 
                { 
                        cout  <<  "Illegal  Input,Please  Input  Again:"; 
                        delete[]  str; 
                } 
        } 
} 

int  GetPriority(char  sy)//设置各个操作符的优先级 
{ 
        switch  (sy) 
        { 
        case  '#': 
                return  0; 
        case  '(': 
                return  1; 
        case  '+': 
        case  '-': 
                return  3; 
        case  '*': 
        case  '/': 
                return  5; 
        case  ')': 
                return  6; 
        default: 
                return  -1; 
        } 
} 


void  AddSpace(char*&  arr)//给转成的后缀表达式的数字和符号添加空格,区分每个字符 
{ 
        *arr  =  '  '; 
        arr++; 
} 

char*  GetBack()//获取后缀表达式的函数 
{ 
        char*  middle  =  new  char[30]; 
        char*  back  =  new  char[30]; 
        char*  backend  =  back; 
        InPut(middle); 
        SeqStack<char>  s; 
        s.push('#'); 
        while  (*middle) 
        { 
                if  (Number(*middle)  ||  *middle  ==  '.')//如果是数字或者小数的话,直接输出 
                { 
                        *back  =  *middle; 
                        back++,  middle++; 
                } 
                else 
                { 
                        if  (Number(*(back  -  1)))//只有他的上一个时数字的话,才继续给空格 
                                                                        //否则遇到多个操作符,则输出域会存在多个空格 
                        { 
                                //*back  =  '  '; 
                                //back++; 
                                AddSpace(back); 
                        } 
                        if  (*middle  ==  ')')//如果右括号的话,输出所有操作符直到遇到左括号,并抛弃相对应的一堆括号 
                        { 
                                while  (s.Gettop()  !=  '(') 
                                { 
                                        *back  =  s.Gettop(); 
                                        s.pop(); 
                                        back++; 
                                        AddSpace(back); 
                                } 
                                middle++; 
                                s.pop();//抛弃左括号 
                        } 
                        else  if  (*middle  ==  '(')//遇到左括号,则进入栈 
                        { 
                                s.push(*middle);  middle++; 
                        } 
                        else  if  (GetPriority(*middle)  >  GetPriority(s.Gettop()))//如果栈内的操作符优先级高于栈外的优先级,则入栈 
                        { 
                                s.push(*middle);  middle++; 
                        } 
                        else  if  (GetPriority(*middle)  <=  GetPriority(s.Gettop())) 
                                                                                                          //如果栈内的操作符优先级低于或等于栈外的优先级,输出栈内的符号,并入栈栈外的符号 
                        { 
                                *back  =  s.Gettop(); 
                                s.pop(); 
                                s.push(*middle); 
                                back++;  middle++; 
                                AddSpace(back); 
                        } 
                } 
        } 
        while  (s.Gettop()  !=  '#')//中缀表达式遍历完成,但是=栈中还有符号存在,一一出栈输出 
        { 
                AddSpace(back); 
                *back  =  s.Gettop(); 
                s.pop();  back++; 
        } 
        *back  =  '\0'; 
        //cout  <<  "The  Back  Is:  "  <<  backend  <<  endl; 
        return  backend; 
} 

double  GetNumber(char*&  arr) 
{ 
        //因为输出为char*,所以可能两位数以上的数字被拆开,此函数为正确得到数字 
        double  sum[10]  =  {  0  };  int  i  =  0;  double  result  =  0; 
        while  (*arr  !=  '  ') 
        { 
                sum[i]  =  *arr-48; 
                i++; 
                arr++; 
        } 
        int  k  =  i  -  1; 
        for  (int  j  =  0;  j  <  i;  j++,k--) 
        { 
                result  +=  (sum[j]  *  pow(10,  k)); 
        } 
        return  result; 
} 

double  Cauculate(char  ch,  double  left,  double  right)//各个操作符对应的操作 
{ 
        switch  (ch) 
        { 
        case  '+': 
                return  left  +  right; 
        case  '-': 
                return  left  -  right; 
        case  '*': 
                return  left  *  right; 
        case  '/': 
                return  left  /  right; 
        default: 
                return  0; 
                break; 
        } 
} 

double  CountBack(char*  back) 
{ 
        SeqStack<double>  s; 
        while  (*back) 
        { 
                if  (Number(*back))//遇到数字 
                { 
                        s.push(GetNumber(back));//将正确的数字入栈 
                } 
                else  if  (*back  ==  '  ') 
                { 
                        back++;//遇到空格跳过 
                } 
                else 
                { 
                        double  a  =  s.Gettop(); 
                        s.pop(); 
                        double  b  =  s.Gettop(); 
                        s.pop(); 
                        s.push(Cauculate(*back,  b,  a));//遇到符号时,取栈顶的第二个数和第一个数求解,并入栈 
                        back++; 
                } 
        } 
        while  (s.getSize()  >=  2)//最终栈内存在的数大于2时,继续计算,直到只剩下一个数 
        { 
                double  a  =  s.Gettop(); 
                s.pop(); 
                double  b  =  s.Gettop(); 
                s.pop(); 
                s.push(Cauculate(*back,  b,  a)); 
        } 
        //返回这个数字,既是最终结果 
        return  s.Gettop(); 
} 
int  main() 
{ 
        cout<<CountBack(GetBack())<<endl;; 
        return  0; 
}

6.循环队列的实现

const int QueueSize=100;
template <typename DataType>
class CirQueue{ 
	public: 
        	CirQueue(); 
        	~CirQueue();
//循环队列是静态存储分配,在循环队列变量退出作用域时自动释放所占内存单元,因此,循环队   列无需销毁,虚构函数为空
        	void EnQueue(DataType  x); 
        	DataType DeQueue(); 
        	DataType GetHead(); 
		int Empty();
		void  PrintQueue()
private: 
        DataType  data[QueueSize]; 
        int  front,rear;
}; 

template  <typename DataType> 
CirQueue<DataType>::CirQueue() 
{ 
        front  =  rear  =  QueueSize-1;    
        //初始化一个空的循环队列只需将对头front和队尾rear同时指向数组的某一位置,一般是数组的高端
} 

template  <typename DataType> 
void CirQueue<DataType>::EnQueue(DataType  x) 
{ 
        if((rear+1)%QueueSize==front) cout<<"full"<<endl;    //牺牲一个存储单元
	rear=(rear+1)%MaxSize;    //队尾指针在循环意义下加一
	data[rear]=x;    //在队尾处插入元素
} 

template  <typename DataType> 
DataType CirQueue<DataType>::DeQueue() 
{ 
        if(rear==front) cout<<"empty"<<endl;
	front=(front+1)%QueueSize;    //对头在循环意义下加一
	return data[front];   //返回队头元素
} 
template <typename DataType>
DataType CirQueue<DataType>::GetHead()
{
	if(rear==front) cout<<"empty"<<endl;
	return data[(front +1)%QueueSize];    //注意不修改队头指针(front指向一个空的)
}
template  <typenamae DataType> 
int CirQueue<DataType>::Empty() 
{
	if(rear==front) return 1;
}

7.循环队列重新排列顺序栈

(exchange方法自己想的有点复杂)
设顺序栈S中有2n个元素,从栈顶到栈底的元素依次为,要求通过一个循环队列重新排列栈中元素,使得从栈顶到栈底的元素依次为。请设计算法实现该操作,要求空间复杂度和时间复杂度均是O(n)。【输入格式】栈的长度(n/2)以及元素(中间用空格隔开)
【输出格式】经过队列相应操作后的序列。
【输入样例】
3
1 2 3 4 5 6
【输出样例】6 4 2 5 3 1

提示:操作步骤:
1、将所有元素出栈并入队;
2、依次将队列元素出队,如果是偶数结点,则再入队,如果是奇数结点,则入栈;
3、将奇数结点出栈并入队;
4、将偶数结点出队并入栈;
5、将所有元素出栈并入队;
6、将所有元素出队并入栈即为所求;

#include  <iostream> 
#include  <stack>     //栈
#include  <queue>     //队列
using  namespace  std; 

stack<int>  seqStack; 
queue<int>  cirQueue; 
int  n; 
void  init(int  len) 
{ 
        for(int  i=0;i<2*len;++i){ 
                int  elem; 
                cin>>elem; 
                seqStack.push(elem); 
        } 
} 
void  exchange() 
{ 
   int a,b,c,d,e,f;
   int count=0;
   for(int i=0;i<n*2;i++)    //将所有元素出栈并入队
   {
       a=seqStack.top();
       seqStack.pop();
       cirQueue.push(a);
       count++;
   }
   for(int i=0;i<n*2;i++)	//依次将队列元素出队,如果是偶数结点,则再入队,如果是奇数结点,则入栈
   {		
   	b=cirQueue.front();    //取队头元素					  
   	cirQueue.pop();		
   	if(count%2==0) cirQueue.push(b);		
   	else seqStack.push(b);		
   	count--;	
   }
   for(int i=0;i<n;i++)	    //将奇数结点出栈并入队
   {		
   	c=seqStack.top();		
   	seqStack.pop();		
   	cirQueue.push(c);	
   }
   for(int i=0;i<n;i++)	    //将偶数结点出队并入栈
   {		
   	d=cirQueue.front();		
   	cirQueue.pop();		
   	seqStack.push(d);	
   }
   for(int i=0;i<n;i++)	    //将所有元素出栈并入队
   {		
   	e=seqStack.top();		
   	seqStack.pop();		
   	cirQueue.push(e);	
   }
   for(int i=0;i<n*2;i++)	//将所有元素出队并入栈即为所求
   {		
   	f=cirQueue.front();		
   	cirQueue.pop();		
   	seqStack.push(f);	
   }			
} 
void  printStack() 
{ 
        while(!seqStack.empty()){ 
                cout<<seqStack.top()<<"  "; 
                seqStack.pop(); 
        } 
        cout<<endl; 
} 
int  main() 
{ 
        cin>>n; 
        init(n); 
        exchange(); 
        printStack(); 
        return  0; 
} 

8.循环链队列的入队和出队

假设以不带头结点的循环链表表示非空队列,并且只设一个指针指向队尾结点,但不设头指针。试设计相应的入队和出队的算法。
【输入说明】 入队次数m以及m个入队元素;(中间用空格隔开) 出队次数n;
【输出说明】执行m次入队操作和n次出队操作后,打印队列中的元素:如果队列为空则输出“Empty”。

#include  <iostream> 
using  namespace  std; 

template  <class  DataType> 
struct  node{ 
        DataType  data; 
        node<DataType>*  next; 
}; 

template  <class  DataType> 
class  cirLinkQueue{ 
public: 
        cirLinkQueue(); 
        cirLinkQueue(DataType  a[],int  n); 
        void  enQueue(DataType  elem); 
        bool  deQueue(); 
        void  printQueue(); 
private: 
        node<DataType>*  rear; 
}; 

template  <class  DataType> 
cirLinkQueue<DataType>::cirLinkQueue() 
{ 
        rear  =  NULL; 
} 

template  <class  DataType> 
cirLinkQueue<DataType>::cirLinkQueue(DataType  a[],int  n) 
{ 
        if(n  ==  1){ 
                rear  =  new  node<DataType>; 
                rear->data  =  a[0]; 
                rear->next  =  rear; 
        } 
        else{ 
                rear  =  new  node<DataType>; 
                rear->data  =  a[0]; 
                rear->next  =  rear; 
                for(int  i=1;i<n;++i){ 
                        node<DataType>*  s  =  new  node<DataType>; 
                        s->data  =  a[i]; 
                        s->next  =  rear->next;    //先右后左
                        rear->next  =  s; 
                        rear  =  s; 
                } 
        } 
} 

template  <class  DataType> 
void  cirLinkQueue<DataType>::enQueue(DataType  elem)     //入队
{ 
         node<DataType>* s = new node<DataType>;
 	s->data=elem;
 	if(rear==NULL)
 	{
  		rear=s;
  		rear->next=s;
 	}
 	else
 	{
 		s->next=rear->next;
  		rear->next=s;
  		rear=s;
 	}

} 

template  <class  DataType> 
bool  cirLinkQueue<DataType>::deQueue()     //出队
{ 
        node<DataType>* q=NULL;
 	if(rear==NULL) return 0;
 	q=rear->next;
 	if(q==rear) 
 	{
     		rear=NULL;
 	}
 	else 
        {
              rear->next=q->next;
      	      delete q;
   	}
        return 1;     
  
} 

template  <class  DataType> 
void  cirLinkQueue<DataType>::printQueue() 
{ 
        if(rear  ==  NULL) 
                cout<<"Empty"<<endl; 
        else{ 
                node<DataType>*  p  =  rear->next; 
                while(p  !=  rear){ 
                        cout<<p->data<<"  "; 
                        p  =  p->next; 
                } 
                cout<<p->data<<endl; 
        } 
} 
int  main() 
{ 
        cirLinkQueue<int>  Q; 
        int  m,n; 
        cin>>m; 
        while(m--){ 
                int  elem; 
                cin>>elem; 
                Q.enQueue(elem); 
        } 
        cin>>n; 
        while(n--){ 
                bool  res  =  Q.deQueue(); 
                if(!res)  break; 
        } 
        Q.printQueue(); 
        return  0; 
} 
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值