【数据结构】栈、队列、堆总结

本文详细介绍了如何使用栈和队列实现各种数据结构操作,包括用栈实现队列、用队列实现栈、带有最小值的栈、合法的出栈序列判断、简单计算器的实现、求第K大数字以及寻找动态中位数的方法,通过具体的算法思想和程序实现,展示了数据结构在实际问题中的应用。
摘要由CSDN通过智能技术生成

零、基本操作##

/*栈的基本操作:*/
std::stack<int> s;
s.top();
s.push();
s.pop();
s.empty();
s.size();

/*队列的基本操作:*/
std::queue<int> q;
q.front();
q.push(x);
q.back();
q.pop();
q.empty();
q.size();
/*堆的基本操作*/
int main()
{
	std::priority_queue<int> big_heap;
	std::priority_queue<int,std::vector<int>,std::greater<int> >small_heap;//创建最小堆
	std::priority_queue<int,std::vector<int>,std::less<int> >big_heap2;//创建最大堆

	if(big_heap.empty())//判断堆是否为空
	{
		printf("big_heap is empty!!!\n");
	}

	int test[] = {6,10,1,7,99, 4,33};
	for(int i = 0;i< 7 ;i++)
	{
		big_heap.push(test[i]);//堆插入
	}

	printf("big_heap.top = %d\n",big_heap.top());//取堆顶元素
	big_heap.push(1000);
	printf("big_heap.top = %d\n ",big_heap.top());

	for(int  i =0; i<3; i++)
	{
		big_heap.pop();//删除堆顶
	}
	printf("big_heap.top = %d \n",big_heap.top());
	printf("big_heap.size = %d\n ",big_heap.size());//求堆中元素个数
	return 0;

}

一、用栈实现队列

**1.0题目:**设计一个队列,队列支持如下操作,这些操作的算法复杂度需要的是常数级,O(1),队列的内部存储数据结构的栈,栈的方法只能包括push(),top(),pop(),size(),empty(),等标准的栈方法;
**1.1算法思想:**使用一个临时栈,一个数据栈,先将所有元素入数据栈中,当数据栈不为空时,将数据栈中所有元素按顺序弹入临时栈,再将临时栈弹入数据栈即可。
1.2程序实现

#include<iostream>
#include<stack>
using namespace std;
class Myqueue
{
public:

	void push(int x)
	{
		std::stack<int> temp;
		while(!_data.empty())
		{
			temp.push(_data.top());
			_data.pop();
		}
		temp.push(x);
		while(!temp.empty())
		{
			_data.push(temp.top());
			temp.pop();
		}
	}
	
	int pop()
	{
		int x = _data.top();
		_data.pop();
		return x;
	}

	int front()
	{
		return _data.top();
	}

	bool empty()
	{
		return _data.empty();
	}

	std::stack<int> _data;
};



int main()
{
	Myqueue Q;
	Q.push(111);
	Q.push(222);
	Q.push(333);
	Q.push(444);
	Q.push(555);
	Q.push(666);
	Q.push(777);
	Q.push(888);
	printf("%d\n",Q.front());

	Q.pop();
	printf("%d\n",Q.front());

	Q.pop();
	Q.pop();
	Q.pop();
	printf("%d\n",Q.front());
	
	printf("%d\n",Q.empty());
	Q.pop();
	Q.pop();
	Q.pop();
	Q.pop();

	printf("%d\n",Q.empty());

	return 0;
}

1.3结果展示

二、用队列实现栈

2.0题目设计一个栈,支持如下操作,这些操作算法复杂度需要的时常数阶,O(1),栈的内部存储数据的结构为队列,队列的方法只能包括push()、peek()(front())、pop()、size(),empty()等标准的队列方法;
**2.1算法思想:**使用一个临时队列,一个数据队列,先将要遍历的某个元素入临时队列,再将数据队列中所有元素入临时队列,当临时队列不为空时,再将临时栈弹入数据栈即可。
2.2程序实现

#include<iostream>
#include<queue>
using namespace std;
class Mystack
{
public:
	void push(int x)
	{
		std::queue<int> temp;
		temp.push(x);
		while(!_data.empty())
		{
			temp.push(_data.front());
			_data.pop();
		}

		while(!temp.empty())
		{
			_data.push(temp.front());
			temp.pop();
		}

	}

	int pop()
	{
		int x = _data.front();
		_data.pop();
		return x;
	}

	int top()
	{
		return _data.front();
	}

	bool empty()
	{
		return _data.empty();
	}
	std::queue<int> _data;
};


int main()
{
	Mystack s;
	s.push(10);
	s.push(20);
	s.push(30);
	s.push(40);
	s.push(50);
	s.push(60);
	s.push(70);
	s.push(80);
	printf("%d\n" , s.top());

	s.pop();
	s.pop();
	s.pop();
	printf("%d\n" , s.top());	
	s.pop();
	printf("%d\n" , s.top());	
	
	printf("%d\n" , s.empty());	
	s.pop();
	s.pop();
	s.pop();
	s.pop();
	printf("%d\n" , s.empty());	
	return 0;
}

2.3结果展示

三、包含min的栈

**3.1题目:**设计一个栈,支持如下操作,这些操作的算法复杂度需要的是常数级,O(1)
(1)push(x)
(2)pop()
(3)top()
(4)getMin()
**3.2算法思想:**设置两个栈,一个数据栈一个最小值栈,每次在往数据栈中压入元素时,将其与最小值栈的栈顶作比较,将较小的保存在最小值栈中,这样一来,最小值栈栈顶将保留所有元素中的最小值,在查找时,直接取最小值栈的栈顶即可。
3.3程序实现

#include<iostream>
#include<stack>
using namespace std;

class MinStack
{
public:
    MinStack() 
	{
    }
	 void push(int x)
	{
    	_data.push(x);
    	if (_min.empty())
		{
	    	_min.push(x);
	    }

		  else 
			  {
				  if(x > _min.top())
		            {
		  	          x = _min.top();
		              }
			        _min.push(x);
	             }
        	}

	void pop()
	{
		_data.pop();
		_min.pop();
	}

	int top()
	{
		return _data.top();
	}

	int getMin()
	{
		return _min.top();
	}

private:
	std::stack<int>  _data;
	std::stack<int>  _min;
};


int main()
{
	MinStack s;
	s.push(3);
	printf("%d\n",s.top());
	printf("%d\n",s.getMin());

	s.push(4);
	printf("%d\n",s.top());
	printf("%d\n",s.getMin());

	s.push(-77);
    printf("%d\n",s.top());
	printf("%d\n",s.getMin());
	
	s.push(100);
	printf("%d\n",s.top());
	printf("%d\n",s.getMin());

	return 0;
}

3.4结果展示

四、合法的出栈序列

**4.1题目:**给出一个序列1,判断该序列1是否为某个已知序列2的出栈序列;
**4.2算法思想:**将带带判断的序列存入一个队列中,将已知序列依次压入栈中,每次压入时,将其与队头元素比较,如果相等,就将队头弹出,将栈顶弹出,如果不等,就继续入站,循环以上操作。
4.3程序实现

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

bool Is_correct_order(std::queue<int> &order)
{
	std::stack<int> s;
	for(int  i = 1; i<order.size();++i)
	{
		s.push(i);
		while(!s.empty()&& s.top()==order.front())
		{
			order.pop();
			s.pop();
		}
	}
	if(!s.empty())
	{
		return false;
	}
	return true;
}

int main(){
	int n;
	int train;
	scanf("%d", &n);
	while(n){
		scanf("%d", &train);
		while (train){
			std::queue<int> order;
			order.push(train);
			for (int i = 1; i < n; i++){
				scanf("%d", &train);
				order.push(train);
			}
			if (Is_correct_order(order)){
				printf("Yes\n");
			}
			else{
				printf("No\n");
			}
			scanf("%d", &train);
		}
		printf("\n");
		scanf("%d", &n);
	}
	return 0;
}

4.4结果展示

五、实现简单的计算器

**5.1题目:**设计一个简单的计算器,输入一个字符串存储的数据表达式,可以计算包括“(”,“)”,“+”,“-”四种符号的数学表达式,输入的数学表达式字符串保证是合法的,输入的数学表达式中可能存在空格字符
**5.2算法思想:**维护两个栈,一个存放数字字符,一个存放符号,设计一个标记,每次当遇到"+“或者”-"时,将标记设置为1,将计算结果保存在数字栈中,当遇到”(“时,则不计算,直到将表达式所有的元素都处理完。;
5.3程序实现

#include<iostream>
#include <string>
#include <stack>
using namespace std;

class Solution 
{
public:
	int calculate(std::string s)
	{
		static const int STATE_BEGIN = 0;
		static const int NUMBER_STATE = 1;
		static const int OPERATION_STATE = 2;
		std::stack<int> number_stack;
		std::stack<char> operation_stack;
		int number = 0;
		int STATE = STATE_BEGIN;
		int compuate_flag = 0;

		for (int i = 0; i < s.length(); i++)
		{
			if (s[i] == ' ')
			{
				continue;
			}
			switch(STATE)
			{
			case STATE_BEGIN:
				if (s[i] >= '0' && s[i] <= '9')
				{
					STATE = NUMBER_STATE;
				}
				else{
					STATE = OPERATION_STATE;
				}
				i--;
				break;
			case NUMBER_STATE:
				if (s[i] >= '0' && s[i] <= '9')
				{
					number = number * 10 + s[i] - '0';
				}
				else{
					number_stack.push(number);
					if (compuate_flag == 1)
					{
						compute(number_stack, operation_stack);
					}
					number = 0;
					i--;
					STATE = OPERATION_STATE;
				}
				break;
			case OPERATION_STATE:
				if (s[i] == '+' || s[i] == '-')
				{
					operation_stack.push(s[i]);
					compuate_flag = 1;
				}
				else if (s[i] == '(')
				{
					STATE = NUMBER_STATE;
					compuate_flag = 0;
				}
				else if (s[i] >= '0' && s[i] <= '9')
				{
					STATE = NUMBER_STATE;			  		
					i--;
				}
				else if (s[i] == ')'){
					compute(number_stack, operation_stack);
				}
				break;
			}
		}
		if (number != 0)
		{
			number_stack.push(number);
			compute(number_stack, operation_stack);
		}
		if (number == 0 && number_stack.empty())
		{
			return 0;
		}
		return number_stack.top();
	}
private:
	void compute(std::stack<int> &number_stack,
		std::stack<char> &operation_stack)
	{
		if (number_stack.size() < 2)
		{
			return;
		}
		int num2 = number_stack.top();
		number_stack.pop();
		int num1 = number_stack.top();
		number_stack.pop();
		if (operation_stack.top() == '+')
		{
			number_stack.push(num1 + num2);
		}
		else if(operation_stack.top() == '-')
		{
			number_stack.push(num1 - num2);
		}
		operation_stack.pop();
	}
};

int main()
{	
	std::string s = "1+121 - (14+(5-6) )";
	Solution solve;
	printf("%d\n", solve.calculate(s));
	return 0;
}

5.4结果展示

六、求第K大数字

**6.1题目:***已知一个未排序的数组,求这个数组中第K大的数字
6.2算法思想维护一个k个元素的最小堆,遍历序列中的每一个元素,使其与根节点比较,如果小于根节点,则丢弃如果大于根节点,则插入堆中,并删除根节点;直到遍历完所有元素,根节点即为第K大节点
6.3程序实现

#include<iostream>
using namespace std;

class solution 
{
public:
	int FindKlargest(std::vector<int>& nums,int k)
	{
		std::priority_queue<int,std::vector<int>,std::greater<int>> less_heap;
		for(int  i =0; i <nums.size();i++)
		{
			if(less_heap.size()<k)
			{
				less_heap.push(nums[i]);
			}
			else
				if(less_heap.top()<nums[i])
				{
					less_heap.pop();
					less_heap.push(nums[i]);
				}
		   
		 }
		return less_heap.top();
	}

};


int main()
{

	std::vector<int> nums;
	nums.push_back(3);
	nums.push_back(14);
	nums.push_back(11);
	nums.push_back(2);
	nums.push_back(22);
	nums.push_back(67);
	nums.push_back(88);
	nums.push_back(90);
	solution solve ;
	printf("%d\n",solve.FindKlargest(nums,2));
	return 0;
}

6.4结果展示

七、寻找中位数

**7.1题目:**设计一个数据结构,该数据结构动态的维护一组数据,且支持如下操作:
1、添加元素:将整型num添加至数据结构中;
2、返回数据中位数,返回其维护的数据的中位数;
中位数定义:
1、若数据个数为奇数,中位数为该组数排序后中间的数。如:1,2,3,—》2
2、若数据个数为偶数,中位数是该组数排序后中间的两个数字的平均值;如1,2,3,4—》2.5

7.2算法思想维护一个最大堆和最小堆;
(1)最小堆的堆顶大于最大堆的堆顶
(2)最小堆和最大堆元素个数之差不大于1;
(3)每遍历一个元素将其与最大堆的堆顶进行比较;
【1】最大堆,最小堆元素个数相等时,如果当前遍历的元素大于最大堆堆顶元素,则插入最小堆内
否则插入最大堆内
【2】最大堆,最小堆元素个数不相等时,
最大堆元素个数大于最小堆元素:
1)当前元素大于最大堆对顶元素,则插入最小堆内
2)当前元素小于最大堆堆顶元素,则将最大堆堆顶插入最小堆,
将当前元素插入最大堆
最大堆元素个数小于最小堆元素:
1)当前元素小于最大堆对顶元素,则插入最大堆内
2)当前元素大于最大堆堆顶元素,则将最小堆堆顶插入最大堆,
将当前元素插入最小堆
7.3程序实现

#include<iostream>
#include<queue>
using namespace std;
class MedianFinder
{
public:

	void addNum(int num)
	{
		if(big_heap.empty())
		{
			big_heap.push(num);
			return ;
		}

		if(big_heap.size() == small_heap.size())
		{
			if(num < big_heap.top())
			{
				big_heap.push(num);
			}
			else
				small_heap.push(num);
		}

		else if(big_heap.size()>small_heap.size())
		{
			if(num>big_heap.top())
				small_heap.push(num);
			else {
				small_heap.push(big_heap.top());
				big_heap.pop();
				big_heap.push(num);
			}
		}

		else if(big_heap.size()<small_heap.size())
		{
			if(num <small_heap.top())//
				big_heap.push(num);
			else
			{
				big_heap.push(small_heap.top());
				small_heap.pop();
				small_heap.push(num);
			}
		}
	}
	double findMedian()
	{
		if(big_heap.size()==small_heap.size())
		{
			return (big_heap.top()+small_heap.top())/2;
		}
		else if(big_heap.size()>small_heap.size())
		{
			return big_heap.top();
		}
		else return small_heap.top();

	}

	std::priority_queue<int,std::vector<double>,std::greater<double>> small_heap;
	std::priority_queue<int,std::vector<double>,std::less <double>>  big_heap;//注意
};
int main()
{
	MedianFinder M;
	M.addNum(2);
	M.addNum(1);

	printf("%lf\n",M.findMedian());

	M.addNum(4);
	printf("%lf\n",M.findMedian());

	M.addNum(3);
	printf("%lf\n",M.findMedian());
	return 0;
}

7.4结果展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值