每日算法之4

每日算法之4

1.使用两个栈实现一个队列

//基础知识:由于栈具有先进后出的特点,如果需要在栈中寻找指定元素,需要的时间复杂度为O(n),如果需要在
		//O(1)的时间访问,必须对栈结构进行改进,需要设计两个栈,一个负责存储,另一个复杂存储最小值

//问题描述:使用两个栈实现一个队列的功能

//算法分析:由于栈先进后出,只需要设计两个栈,将元素推入一个栈s1,出栈推入s2,之后从s2出栈,反反得正

//算法实现:
template<typename T>
class CQueue{
public:
    void appendTail(const T&);//请实现次队列的尾部插入元素和头部删除元素的函数
    T deleteHead();
    void show();
    
private:
    stack<T> stack1;
    stack<T> stack2;
};

template<typename T>
void CQueue<T>::appendTail(const T& e){
    stack1.push(e);//尾部插入只需要推入栈1即可
}

template<typename T>
T CQueue<T>::deleteHead(){
    if(stack2.empty()){
        while(!stack1.empty()){
            T& data=stack1.top();
            stack1.pop();
            stack2.push(data);
        }
    }
    if(stack2.empty())
        throw "queue is empty!";
    
    T head=stack2.top();
    stack2.pop();
    
    return head;
}
template<typename T>
void CQueue<T>::show(){
	cout<<"stack1 size of:"<<stack1.size()<<endl;
	cout<<"stack2 size of:"<<stack2.size()<<endl;
}

//测试用例:
#include <iostream>
#include <stack>
#include <exception>
int main(){
	CQueue<int> queue;
	queue.appendTail(2);
	queue.appendTail(4);
	queue.show();
	try{
		queue.deleteHead();
		queue.show();
		
		queue.deleteHead();
		queue.show();
		
		queue.deleteHead();
	
	}catch(const char* e){
		cout<<e;
	}
}

2.使用两个队列实现一个栈

//由于两个队列都是先进先出,所以直接相连,无法直接正正得负,所以必须重新分析,考虑到依次入队q1元素
	//1,2,3,4想要出栈时删除4,必须先将1,2,3出队,依次放入q2,最后才能删除4,也就是说,必须
	//分两种队列,一种用于接受新入队的元素,删除时,需要另外一个空队列作为接受前面元素的辅助队列

//算法实现:
template<typename T>
class CStack{
  public:    
    void Cpush(const T&);
    T& Cpop();
    void show();
  private:
    queue<T> m_q1;
    queue<T> m_q2;
};

template<typename T>
void CStack<T>::Cpush(const T& e){
	
	if(m_q1.empty()){
		m_q2.push(e);
	}
	else if(m_q2.empty()){
		m_q1.push(e);
	}else{
		throw "push error!";
	}
} 

template<typename T>
T& CStack<T>::Cpop(){
	if(m_q1.empty()&&m_q2.empty()){
		throw "pop error!";
	}
	if(m_q1.empty()){
		while(m_q2.size()!=1){
			T& data=m_q2.front();
			m_q2.pop();
			m_q1.push(data);
		}
		T& popElem=m_q2.front();
		m_q2.pop();
		
		return popElem;
	}else{
		while(m_q1.size()!=1){
			T& data=m_q1.front();
			m_q1.pop();
			m_q2.push(data);
		}
		T& popElem=m_q1.front();
		m_q1.pop();
		
		return popElem;
	}
}
template<typename T>
void CStack<T>::show(){
	cout<<"队列1的元素大小:"<<m_q1.size()<<endl;
	cout<<"队列2的元素大小:"<<m_q2.size()<<endl;
}

//测试用例:
int main(){
	CStack<int> s;
	s.Cpush(1);
	s.Cpush(2);
	s.Cpush(3);
	s.Cpush(4);
	s.Cpush(5);
	s.Cpush(6);
	s.show();
	
	cout<<"出栈元素:"<<s.Cpop()<<endl;
	cout<<"出栈元素:"<<s.Cpop()<<endl;
	cout<<"出栈元素:"<<s.Cpop()<<endl;
	s.Cpush(7);
	cout<<"出栈元素:"<<s.Cpop()<<endl;
	s.Cpush(8);
	s.show();
}
/*输出结果:
	队列1的元素大小:0
    队列2的元素大小:6
    出栈元素:6
    出栈元素:5
    出栈元素:4
    出栈元素:7
    队列1的元素大小:0
    队列2的元素大小:4
*/
//可见已经实现栈后进先出的特点!!

3.重温斐波那契数列

//使用一般的递归实现
int fibonacci(int n){
    if(n==0)
        return 0;
    if(n==1)
        return 1;
    if(n>1)
        return fibonacci(n-1)+fibonacci(n-2);
}
//使用尾递归实现
long long fibonacci_trail(long long n,long long firstRes,long long secondRes){
	if(n<0)
		return -1; 
	if(n==0)
		return 0;
	if(n==1)
		return 1;
	if(n==2)
		return firstRes+secondRes;
	return fibonacci_trail(n-1,secondRes,firstRes+secondRes);
} 

//解决实际问题

//青蛙跳台阶:青蛙可以一次跳1个台阶,也可以一次跳2个台阶,现在n级台阶公有多少种跳法
//对于1级台阶,只有一种跳法,对于2级台阶,有2种跳法,对于n>2级台阶,第一次跳1阶,剩下共f(n-1)
//第一次跳2阶,剩下共f(n-2)种跳法,所以一共f(n-1)+f(n-2)种跳法

//可以发现,青蛙跳台阶就是求斐波那契数列的问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值