数据结构与算法再探(一)栈与队列的应用

栈应用举例

栈是操作受限的线性表,典型生活中的用例:压入子弹。std::stack 类是一种容器适配器,它给予程序员栈的功能,特别是 FILO(先进后出)数据结构。该类模板用处为底层容器的包装器,只提供特定函数集合。栈从被称作栈顶的容器尾部推弹元素。

C++ stack的基本操作
s.pop()修改器删除栈顶元素,但不返回该元素的值
swap()
s.push(item)创建一个新元素压入栈顶,该元素通过拷贝或移动item而来,或者由args构造
s.emplace(args)
s.top()元素访问返回栈顶元素,但是不将元素弹出栈
empty()、size()容量empty检查容器是否为空,size返回元素数
栈默认基于deque实现,也可以在list或vector之上实现

 std::stack的基本操作:

#include <iostream>
#include <stack>
using namespace std;
int main() {
  stack<int> s;

  // push() 压入元素
  s.push(1); 
  s.push(2);
  s.push(3);
//容量
  cout << "s.size() = " << s.size() << endl; 
  cout << "s.empty() = " << s.empty() << endl;
  if (!s.empty())
    cout << "栈顶元素s.top() = " << s.top() << endl;
//元素访问
  s.pop();  // 弹出栈顶元素
  cout << "s.size() = " << s.size() << " s.empty() = " << s.empty() << endl;
  if (!s.empty())
    cout << "s.top() = " << s.top() << endl;
   //推入新元素到 stack 顶。原位构造元素,即不进行移动或复制操作
  s.emplace(3);
  stack<int> s1;//空栈
  s1.swap(s);  // s和s1进行交换

  cout << "s.size() = " << s.size() << "  s.empty() = " << s.empty() << endl;
  if (!s.empty())
    cout << "栈顶元素,即s.top() = " << s.top() << endl;
  else
    cout << "栈空不能使用top访问栈顶元素" << endl;

  cout << "s1.size() = " << s1.size() << "  s1.empty() = " << s1.empty() << endl;
  if (!s1.empty())
    cout << "栈顶元素,即s1.top() = " << s1.top() << endl;
  return 0;
}

应用实例(一):括号匹配

输入给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效

bool isValid(string s) {
        stack<char> sta;
        if (s.size() % 2 == 1) {
            return false;
        }
        for (auto ch : s) {
            if (sta.empty() || ch == '{' || ch == '[' || ch == '(') {
                sta.push(ch);
            } else if (ch == ']' && !sta.empty() && sta.top() == '[')
                sta.pop();
            else if (ch == '}' && !sta.empty() && sta.top() == '{')
                sta.pop();
            else if (ch == ')' && !sta.empty() && sta.top() == '(')
                sta.pop();
            else
                sta.push(ch);
        }
        return sta.empty();
    }

非栈方式

bool isValid(string s) {
    int len=s.length()/2;
	std::string::size_type n;
	for(int i=0;i<len;i++){
	    n=s.find("()");
		if(n != std::string::npos){
		s.replace(s.find("()"),2,"");
		}
		n=s.find("{}");
		if(n != std::string::npos){
		s.replace(s.find("{}"),2,"");
		}
		n=s.find("[]");
		if(n != std::string::npos){
			//cout<<f;
		s.replace(s.find("[]"),2,"");
		}
	}

	return s.empty();
    }

队列的应用

队:

一种先进先出的数据结构,std::queue也是一种容器适配器,遵循先进先出FIFO原则,其中从容器一端插入元素,另一端提取元素。

priority_queue是C++标准库中的一个容器适配器,用于实现优先队列的数据结构。优先队列是一种特殊的队列,其中的元素按照一定的优先级进行排序,每次取出的元素都是优先级最高的。它的底层实现通常使用堆(heap)数据结构。它提供常数时间的(默认)最大元素查找,对数代价的插入与提取。可以通过用户提供的 Compare 更改顺序,例如,用 std::greater<T> 将导致最小元素作为top()出现。默认使用std::less比较使得最大元素出现在堆顶。priority_queue 的作用类似于管理某些随机访问容器中的堆,其优势是不可能意外使堆失效。

C++的队列适配器queue和priority_queue适配器定义在queue头文件中,queue默认基于deque实现,也可以用list或vector实现,priority_queue默认基于vector实现,也可以用deque实现
q.pop()移除quene的首元素或priority_queue的最高优先级的元素
q.front()

返回首元素或尾元素,但是不删除此元素,q.back只适用于quene

q.back()
q.top()返回最高优先级元素不删除该元素只适用于priority_queue
q.push(item)在queue末尾或priority_queue中恰当位置创建一个值为item的元素或者由args构造
q.emplace(args)

 std::queue 基本操作

#include <iostream>
#include<queue>
using namespace std;
int main()
{
	queue<int> q;	//默认使用 deque
	//queue<double, vector<double>> qVector;	//指定使用 vector
    q.push(1);
	q.push(2);
	q.push(3);
	cout << q.size() << endl;  //元素个数  size() 3
	cout << q.front() << endl; //队头元素 front() 1
	cout << q.back() << endl;  //队尾元素 队尾元素back() 3
    q.pop();                   // 出队pop()   
	cout << q.size() << endl;  //2
	cout << q.front() << endl; //2
	while (!q.empty())         //判空 empty()
    {
		cout << q.front() << " "; //2 3
		q.pop();
	}
	cout << q.size() << endl; //0
	queue<int> q1;
	q1.push(4);
	q1.push(5);
	q1.push(6);
 	cout <<"before swap q size is "<< q.size() <<" before swap q1 size is "<<q1.size()<< endl; //0 3
	q.swap(q1);   //交换
	cout <<"after swap q size is "<< q.size() <<" after swap q1 size is "<<q1.size()<< endl; //3 0
	priority_queue<int> pq;	//直接构造一个空对象,默认为大堆
	priority_queue<int, std::vector<int>, std::greater<int>> pq1; // 构建小堆
	cout<<"----------priority_queue----"<<endl;
	pq.push(1);
	pq.push(2);
	pq.push(3);
	cout<<pq.size()<<"   "<<pq.empty()<<endl; //3  0判空empty 元素数 size
	cout << pq.top() << endl;   //优先级最高的元素 3
	pq1.push(1);
	pq1.push(2);
	pq1.push(3);
	cout<<pq1.size()<<"   "<<pq1.empty()<<endl; //3  0判空empty 元素数 size
	cout << pq1.top() << endl; // 1
	pq1.pop();
	cout<<pq1.size()<<"   "<<pq1.empty()<<endl; //2  0判空empty 元素数 size
	priority_queue<int> pq2;	//直接构造一个空对象,默认为大堆
	cout<<pq2.size()<<"   "<<pq2.empty()<<endl; //0  1判空empty 元素数 size
	pq.swap(pq2); //交换的前提必须是 两个队列构建都是相同的类型的堆
	cout<<pq.size()<<"   "<<pq.empty()<<endl; //0  1判空empty 元素数 size
	cout<<pq2.size()<<"   "<<pq2.empty()<<endl; //3  0判空empty 元素数 size
	return 0;
	
}

队列应用举例:

1、约瑟夫问题

:N个人围成一圈,从第一个人开始报数,数到M的人出圈;再由下一个人开始报数,数到M的人出圈

数组实现:

#include <string>
#include <iostream>
using namespace std;
 int main(){
 	int n,m,flag=0;
	 cin>>n>>m;
 	int count=0,len=1,arr[n+1]={0};
 	for(int i=1;i<=n;i++){
 		arr[i]=i;
	 }
	while(flag!=n)//一共n个人 
	{
		if(arr[len]!=0){//如果数组不为0,就计数已经输出的人将其值赋值为了0 
			count++;				
		}
		if(count==m)//计数值为m输出该点的值并将其赋值为0 
		{
			count=0;
			cout<<arr[len]<<" ";
			arr[len]=0;
			flag++;//记录已经输出个数	
		}
		len=(len+1)%(n+1);//循环一次len++	
	}
	return 0;
 }

队列实现:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    queue<int> que;
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; ++i)
        que.push(i);
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= m - 1; ++j)
        {//将队头的人出队后,再入队到队尾
            que.push(que.front()); 
            que.pop();
        }
        cout << que.front() << ' ';//此时队头是要出列的人 
        que.pop();
    }
    return 0;
}

双向链表

#include<bits/stdc++.h>
using namespace std;
int main()
{
    list<int> li;
    int n, m, ct = 0;
    cin >> n >> m;
    for(int i = 1; i <= n; ++i)
        li.push_back(i);
    list<int>::iterator it = li.begin();
    while(li.empty() == false)
    {
        ct++;
        if(ct == m)
        {
            cout << *it << ' ';
            it = li.erase(it);
            ct = 0;
        }
        else
        	it++;
        if(it == li.end())
            it = li.begin();
    }
    return 0;
}

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值