再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习。

首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个阶段再去探究具体的实现,以及对基本结构的改造!


C++标准库中的基本使用方法:

栈: #include<stack>

定义栈,以如下形式实现: stack<Type> s; 其中Type为数据类型(如 int,float,char等)

常用操作有:

s.push(item);       //将item压入栈顶
s.pop();        //删除栈顶的元素,但不会返回
s.top();        //返回栈顶的元素,但不会删除,,,,,,,,,在出栈时需要进行两步,即先top()获得栈顶元素,再pop()删除栈顶元素
s.size();      //返回栈中元素的个数
s.empty();      //检查栈是否为空,如果为空返回true,否则返回false

 

最基本的用法就是:

stack<int> st;---------------------------------->栈

int first=1;

st.push(first);//入栈1

int second=2;

st.push(second);//入栈2

first=st.top();//first变成了2

st.pop();//出栈

 

队列:#include<queue>

queue<int> q; //定义一个 int 型的队列 ---------------------------------->队列
q.empty()//如果队列为空返回true,否则返回false
q.size() //返回队列中元素的个数

q.push() //在队尾压入新元素
q.front() //返回队首元素的值,但不删除该元素
q.pop() //删除队列首元素但不返回其值
q.back()//返回队列尾元素的值,但不删除该元素

 

另外在队列中还有优先队列,priority_queue<.........>---------------------------------->优先队列

要包含头文件:

#include<functional>
#include<queue>

优先队列支持的操作有:

q.empty()    //如果队列为空,则返回true,否则返回false
q.size()     //返回队列中元素的个数
q.pop()    //删除队首元素,但不返回其值
q.top()    //返回具有最高优先级的元素值,但不删除该元素,注意与传统队列的不同以及和栈的相同点
q.push(item) //在基于优先级的适当位置插入新元素

 

优先队列是我们比较不熟悉的一种结构,下面整体上做一个总结学习:

优先队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序,每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储。

例如:我们常用的操作就是对数据排序,优先队列默认的是数据大的优先级高,所以我们无论按照什么顺序push一堆数,最终在队列里总是top出最大的元素。

所以,优先队列在一些定义了权重的地方很有用,priority_queue特别之处在于,允许用户为队列中存储的元素设置优先级。这种队列不是直接将新元素放置在队列尾部,而是放在比它优先级低的元素前面。标准库默认使用<操作符来确定对象之间的优先级关系,所以如果要使用自定义对象,需要重载 < 操作符。

 使用上有这么几种类型:

 1 priority_queue<int>que;//采用默认优先级构造队列 
 2 
 3 priority_queue<int,vector<int>,cmp1>que1;//最小值优先 ,,,,,这里定义底层实现以vector实现
 4 priority_queue<int,vector<int>,cmp2>que2;//最大值优先 
 5 
 6 priority_queue<int,vector<int>,greater<int> >que3;//最小值优先,另外需注意“>>”会被认为错误, 
 7 priority_queue<int,vector<int>,less<int> >que4;//最大值优先 
 8 
 9 priority_queue<number1>que5; //最小优先级队列 --->针对自定义的数据结构
10 priority_queue<number2>que6; //最大优先级队列

1、默认优先级队列,默认的优先级是按照数据的大小来决定的。默认为最大值优先的。

2、设置的最小值或者最大值优先队列,使用一个比较结构来标识来表明比较的方式,这里的cmp为:

 1 struct cmp1  
 2 {  
 3     bool operator ()(int &a,int &b)  
 4     {  
 5         return a>b;//最小值优先  
 6     }  
 7 }; 
 8 
 9 struct cmp2  
10 {  
11     bool operator ()(int &a,int &b)  
12     {  
13         return a<b;//最大值优先  
14     }  
15 }; 

3、采用头文件"functional"内定义的优先级,即greater<int>/less<int>,来标识,除此之外可以不用包含此头文件。

4、或者使用自定义的结构,但结构内需重载操作符<,比如这里的number1和number2:

//自定义数据结构  
struct number1  
{  
    int x;  
    bool operator < (const number1 &a) const  
    {  
        return x>a.x;//最小值优先  
    }  
};  
struct number2  
{  
    int x;  
    bool operator < (const number2 &a) const  
    {  
        return x<a.x;//最大值优先  
    }  
};  

总结,能直接进行数据大小比较的,就是默认为最大值优先a<b,如果要更改,就是用一个cmp,更改为a>b就变成了最小值优先了,而对于无法直接进行比较的数据结构,就自定义一个<运算符重载,制定一个元素进行比较,默认的按照最大值优先,即x<a.x,若要更改就改成x>a.x即可变成最小值优先。


基本用法就是这个样子,需要从题目中进行锻炼,对于栈和队列基本都比较简单,但是对于优先队列就需要重点去掌握了!!!

针对于优先级队列,有人总结出几点常用的功能:(其实大致就是上面的四种类型的用法)

 1、优先队列最基本的功能就是出队时不是按照先进先出的规则,而是按照队列中优先级顺序出队

  知识点:1、一般存放实型类型,可比较大小

      2、默认情况下底层以Vector实现

      3、默认情况下是大顶堆,也就是大者优先级高,可以自定义优先级比较规则

1 priority_queue<int> Q;
2 Q.push(2);
3 Q.push(5);
4 Q.push(3);
5 while(!Q.empty())
6 {
7        cout<<Q.top()<<endl;
8        Q.pop();
9 }//这样就是一个按照顺序排序的输出

2、可以将一个存放实型类型的数据结构转化为优先队列,这里跟优先队列的构造函数相关,

使用的是   priority_queue(InputIterator first,InputIterator last)

给出了一个容器的开口和结尾,然后把这个容器内容拷贝到底层实现(默认vector)中去构造出优先队列。

1 int a[5]={3,4,5,2,1};
2 priority_queue<int> Q(a,a+5);
3 while(!Q.empty())
4 {
5       cout<<Q.top()<<endl;
6       Q.pop();
7 }  

3、可以定义了一个(Node),底层实现以vector实现(第二个参数),优先级为小顶堆(第三个参数)

前两个参数没什么说的,很好理解,其中第三个参数,默认有三写法:

小顶堆:greater<TYPE>

大顶堆:less<TYPE>            --------->需要使用头文件:#include<functional>

 

如果想自定义优先级而TYPE不是基本类型,而是复杂类型,例如结构体、类对象,则必须重载其中的operator(),即cmp


经典例题:Ugly Numbers http://poj.org/problem?id=1338

Input

Each line of the input contains a postisive integer n (n <= 1500).Input is terminated by a line with n=0.

Output

For each line, output the n’th ugly number .:Don’t deal with the line with n=0.

Sample Input

1
2
9
0

Sample Output

1
2
10

此题只使用优先级队列不太能解决问题,解决问题需要两个条件从小到大的排序+无重复,只使用优先级队列可以解决排序,而无重复只能使用自定义逻辑来判断,个人认为使用set能更优雅的解决问题。
下面给出代码,使用set解决问题:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <set>
 4 #include <cmath>
 5 
 6 using namespace std;
 7 
 8 unsigned long result[1500];
 9 
10 void getUgly()
11 {
12     set<unsigned long> s;
13     s.insert(2);
14     s.insert(3);
15     s.insert(5);
16 
17     int i=0;
18     result[i]=1;
19     unsigned long tmp=0;
20     while(i<1500)
21     {
22         i++;
23         tmp=*(s.begin());
24         result[i]=tmp;
25         s.erase(tmp);
26         s.insert(tmp*2);
27         s.insert(tmp*3);
28         s.insert(tmp*5);
29     }
30 }
31 
32 
33 int main()
34 {
35     int n;
36 
37     getUgly();
38     while(cin>>n)
39     {
40         if(n==0)
41             break;
42 
43         cout<<result[n-1]<<endl;
44     }
45     return 0;
46 }
View Code

相关文章:

  • 2021-10-15
  • 2020-06-13
  • 2019-06-01
  • 2021-08-26
  • 2021-09-07
  • 2022-12-23
  • 2021-07-28
  • 2021-12-14
猜你喜欢
  • 2021-08-16
  • 2021-08-22
  • 2022-12-23
  • 2022-12-23
  • 2022-01-24
  • 2019-07-03
  • 2022-02-15
相关资源
相似解决方案