C++ STL 常用各类算法数据结构汇总

STL(standard template library)标准模板库

STL(标准模板库),是目前C++内置支持的library。它的底层利用了C++类模板和函数模板的机制,由三大部分组成:容器、算法和迭代器。
目前STL有六大组件

容器 container
算法 algorthm
迭代器 iterator
仿函数 function object
适配器 adaptor
空间配置器 allocator


算法

二分查找
C++ lower_bound 与 upper_bound 函数
需要头文件:

#include <algorithm>

二分查找的函数有 3 个:

lower_bound(first, last, &val) 算法返回一个非递减序列 [first, last) 中第一个大于等于值 val 的位置;

upper_bound(first, last, &val) 算法返回一个非递减序列 [first, last) 中第一个大于值 val 的位置;

binary_search(first, last, &val) 算法返回一个非递减序列 [first, last) 中是否存在这么一个数,是一个bool值。


std::lower_bound()
功能:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,该位置越界
lower_bound()源码:

int lower_bound(int *array, int size, int key) {
    int first = 0, middle;  //这种操作?
    int half, len;
    len = size;

    while(len > 0) {
        half = len >> 1;    //右移操作,len大小减半
        middle = first + half;
        if(array[middle] < key) {   //在右半序列继续查找
            first = middle + 1;
            len = len - half - 1 ;
        } else              //在左半序列继续查找
            len = half;
    }
    return first;
}

std::upper_bound()
功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置
注意:返回查找元素的最后一个可安插位置,也就是“元素值>查找值”的第一个元素的位置。同样,如果val大于数组中全部元素,返回的是last。(注意:数组下标越界)
upper_bound()源码:

int upper_bound(int *array, int size, int key) {
    int len = size - 1;
    int half, middle;

    while(len > 0) {
        half = len >> 1;
        middle = first + half;
        if(array[middle] > key)    //在左半序列继续查找
            len = half;
        else {                  //在右半序列继续查找
            first = middle + 1;
            len = len - half - 1;
        }
    }
    return first;
}

例子:

void main()
{
    vector<int> t;
    t.push_back(1);
    t.push_back(2);
    t.push_back(3);
    t.push_back(4);
    t.push_back(6);
    t.push_back(7);
    t.push_back(8);

    int low=lower_bound(t.begin(),t.end(),5)-t.begin();
    int upp=upper_bound(t.begin(),t.end(),5)-t.begin();
    cout<<low<<endl;
    cout<<upp<<endl;
  
    system("pause");
}

结构体例子

#include <cstdio>
#include <algorithm>
using namespace std;
int n,m;
struct WORK
{
    int d,p;
    bool operator <(const WORK x)
    {
        if(x.d==d)return x.p>p;
        return x.d>d;
    }

}work[100010];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&work[i].d,&work[i].p);
    sort(work+1,work+n+1);
    for(int i=1;i<=n;i++)
        printf("%d %d\n",work[i].d,work[i].p);
    int ab;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&ab);printf("ab=%d\n");
        work[0].d=ab;work[0].p=1000000001;
        int temp = lower_bound(work+1,work+n+1,work[0])-work;
        printf("temp=%d\n",temp);
        if(temp-1>0)
            printf("%d\n",work[temp-1].p);
        else
            printf("0\n");
    }
    return 0;
}

如果使用结构体,要自己在结构体里重载比较符。要注意,如果数据结构存储的东西是从1到n而不是0到n-1的话,减下标时要+1。



排序
sort()类函数

函数名功能描述
sort对给定区间所有元素进行排序
stable_sort对给定区间所有元素进行稳定排序
partial_sort对给定区间所有元素部分排序
partial_sort_copy对给定区间复制并排序
nth_element找出给定区间的某个位置对应的元素
is_sorted判断一个区间是否已经排好序
partition使得符合某个条件的元素放在前面
stable_partition相对稳定的使得符合某个条件的元素放在前面

需要头文件:

#include <algorithm>

std::sort()
语法描述:sort(begin,end,cmp),cmp参数可以没有,如果没有默认非降序排序。
基本数据类型排序

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
    int a[5]={1,3,4,2,5};
    sort(a,a+5);
    for(int i=0;i<5;i++)
            cout<<a[i]<<' ';
    return 0;
 }   
  
输出:
1 2 3 4 5 

因为没有cmp函数,默认非降序排序。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int a[5]={1,3,4,2,5};
    sort(a,a+5,cmp);
    for(int i=0;i<5;i++)
            cout<<a[i]<<' ';
    return 0;
 }
  
输出:
5 4 3 2 1

对于基本数据类型来说(类型支持“<”、“>”等比较运算符),是有现成的模板函数的。
equal_to、not_equal_to、greater、greater_equal、less、less_equal。

升序:sort(begin,end,less<data-type>());
降序:sort(begin,end,greater<data-type>());

#include<iostream>
#include<algorithm>
using namespace std;
int  main ( )
{
    int a[20]={2,4,1,23,5,76,0,43,24,65},i;
    for(i=0;i<20;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    sort(a,a+20,greater<int>());//这里的greater是带括号的,cmp的不带的
    for(i=0;i<20;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

输出:
2 4 1 23 5 76 0 43 24 65 0 0 0 0 0 0 0 0 0 0
76 65 43 24 23 5 4 2 1 0 0 0 0 0 0 0 0 0 0 0

STL容器类型排序

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int  main ( )
{
    int i,temp[]={2,4,1,23,5,76,0,43,24,65};
    vector<int> a(temp,temp+10);//用数组初始化vector
    for(i=0;i<a.size();i++)
        cout<<a[i]<<" ";
    cout<<endl;
    sort(a.begin(),a.end());
    for(i=0;i<a.size();i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

输出
2 4 1 23 5 76 0 43 24 65
0 1 2 4 5 23 24 43 65 76

使用反向迭代器来逆向排序

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int  main ( )
{
    int i,temp[]={2,4,1,23,5,76,0,43,24,65};
    vector<int> a(temp,temp+10);//用数组初始化vector
    for(i=0;i<a.size();i++)
        cout<<a[i]<<" ";
    cout<<endl;
    sort(a.rbegin(),a.rend());
    for(i=0;i<a.size();i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

输出
2 4 1 23 5 76 0 43 24 65
76 65 43 24 23 5 4 2 1 0

对于自定义数据类型有两种使用方法
使用cmp函数

#include <cstdio>
#include <algorithm>
using namespace std;
int n;
struct WORK
{
    int d,p;
}work[100010];
bool cmp(WORK x,WORK y)
{
    return x.d<y.d;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&work[i].d,&work[i].p);
    sort(work+1,work+n+1,cmp);
    return 0;
}

数据结构内重载比较符

#include <cstdio>
#include <algorithm>
using namespace std;
int n;
struct WORK
{
    int d,p;
    bool operator <(const WORK x)
    {
        if(x.d==d)return x.p>p;
        return x.d>d;
    }

}work[100010];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&work[i].d,&work[i].p);
    sort(work+1,work+n+1);
    return 0;
}

std::unique()
去重函数
需要头文件:

#include <algorithm>

unique函数属于STL中比较常用函数,它的功能是元素去重。并不是真的删除,而是将后面的不重复元素放到前面来。去重的数据结构不一定要有序,由此可见,该函数必定是扫一遍并对每个数做点什么,如用平衡二叉树实现的话,复杂度可到O(nlog),暴力的话为O(n²)。但是具体怎么实现的我不知道。

函数原型

iterator unique(iterator it_1,iterator it_2);
iterator unique(iterator it_1,iterator it_2,bool cmp);

对两迭代器 [it_1,it_2) 前闭后开区间内的数进行去重,可以自定义cmp相等函数

例子

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

int main()
{
	int a[10] = { 0, 7, 7, 6, 1, 1, 5, 5, 8, 9 };
	int n = unique(a, a + 10) - a;//记住返回的是末尾迭代器而不是数组长度
	cout << n << endl;        // 7
	for (int i = 0; i < 10; i++)
		cout << a[i] << " ";  // 0 7 6 1 5 8 9 5 8 9
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";  // 0 7 6 1 5 8 9 
	return 0;
}

配合STL用法

#include <iostream>     // std::cout
#include <algorithm>    // std::unique, std::distance
#include <vector>       // std::vector

bool myfunction (int i, int j) {
	return (i==j);
}

int main () {
	int myints[] = {10,20,20,20,30,30,20,20,10};           // 10 20 20 20 30 30 20 20 10
	std::vector<int> myvector (myints,myints+9);

	// using default comparison:
  	std::vector<int>::iterator it;
  	it = std::unique (myvector.begin(), myvector.end());   // 10 20 30 20 10 ?  ?  ?  ?
                                                         //                ^

  	myvector.resize( std::distance(myvector.begin(),it) ); // 10 20 30 20 10

  // using predicate comparison:
  	std::unique (myvector.begin(), myvector.end(), myfunction);   // (no changes)

  // print out content:
  	std::cout << "myvector contains:";
  	for (it=myvector.begin(); it!=myvector.end(); ++it)
    	std::cout << ' ' << *it;
  	std::cout << '\n';

  	return 0;
}

输出:
myvector contains: 10 20 30 20 10


算法模板:
链接: https://pan.baidu.com/s/17lrYgvBv7x_FAb8GXFTz8Q 提取码: 49ge

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值