算法的定义+计算的资源+算法的评估+STL

算法的定义+计算的资源+算法的评估+STL

算法的定义:

算法(Algorithm)是对特定问题求解步骤的一种描述,是指令的有限序列。它有以下5特征。

输入:一个算法有零个或多个输入。程序可以没有输入,例如一个定时闹钟程序,它并不需要输入,但是能够每隔一段时间就输出一个报警。
输出:一个算法有一个或多个输出。程序可以没有输入,但是一定要有输出。
有穷性:一个算法必须在执行有穷步之后结束,且每一步都在有穷时间内完成。
确定性:算法中的每一步指令必须有确切的含义,对于相同的输入只能得到相同的输出。
可行性:算法描述的操作可以通过已经实现的基本操作执行有限次来实现。

计算的资源:

程序运行时需要的资源有两种,即计算时间和存储空间。资源是有限的,一个算法对这两个资源的使用程序可以用来衡量该算法的优劣。

时间复杂度:程序运行需要的时间。

空间复杂度:程序运行需要的存储空间。

算法的评估:

一个程序或算法的复杂度有以下可能:

O(1)
计算时间是一个常数,和问题的规模n无关。例如,用公式计算,一次计算的复杂度就是O(1);哈希算法,用hash函数在常数时间内计算出存储位置;在矩阵A[M][N]中查找第i行第j列的元素,只需要访问A[i][j]就够了。

O(log₂n)
计算时间是对数,通常是以2为底的对数,每一步计算后,问题的规模减少一倍。例如在一个长度为n的有序数列中查找某个数,用折半查找的方法只需要log₂n次就能找到。再如分治法,一般情况下,在每个步骤把规模减少一倍,所以一共有O(log2n)个步骤。

O(log₂n)和O(1)没有太大区别。

O(n)
计算时间随规模n线性增长。在很多情况下,这是算法可能达到的最优复杂度,因为对输入的n个数,程序一般需要处理所有的数。再如图问题,有V个点和E个边,大多数图的问题都需要搜索到所有的点和边,复杂度的上限就是O(V+E)。

O(nlog₂n)
这通常是算法能达到的最优复杂度。例如分治法,一共O(log₂n)个步骤,每个步骤对每个数操作一次,所以总复杂度是O(nlog₂n)。用分治法思想实现的快速排序和归并排序算法的复杂度就是O(nlog₂n)。

O(n² )
一个两重循环的算法,复杂度是O()。例如冒泡排序就是典型的两重循环。类似的复杂度有O(n³)等。

O(2的n次幂)
一般对应集合问题,例如一个集合中有n个数,有求输出它的所有子集,子集有2的n次幂个。

O(n!)
在排列问题中,如果要求输出所有的全排列,那么复杂度就是O(n!)。

在上面的复杂度分成两类:1、多项式复杂度,包括O(1)、O(n)、O(nlog₂n)、O(n²)等;2、指数复杂度,包括O(2的n次幂)、O(n!)等。
在这里插入图片描述
然后分享yxc大佬总结的由数据范围反推算法复杂度以及算法内容

由数据范围反推算法复杂度以及算法内容

STL

STL包含容器、迭代器、空间配置器、配接器、算法、仿函数。

1、容器

顺序式容器

顺序式容器包括vector、list、deque、queue、priority_queue、stack等,它们的特点如下。

vector:				动态数组,从末尾能够快速插入与删除,直接访问任何元素。
list:					双链表,从任何地方快速插入与删除。
deque:					双向队列,从前面或后面快速插入与删除,直接访问任何元素。
queue:					队列,先进先出。
priority_queue:		优先队列,最高优先级元素总是第一个出列。
stack:					栈,后进先出。
vector

定义:数组是基本的数据结构,有静态数组和动态数据两种类型。
vector是STL的动态数组,在运行时能根据需要改变数组的大小,能存放任何类型的对象。

vector定义
还可以定义多维数组,例如定义一个二维数组:
vectora[MAXN];

常用操作
vector的常用操作

栈和stack

栈是最基本的数据结构之一,特点是“先进先出”。例如乘坐电梯时,先进电梯的最后出来;一盒泡腾片,最先放进盒子的药片位于最底层,最后被拿出来。
头文件#include<stack>
栈的有关操作:

stack<<Type>Type>s;		*//定义栈,Type为数据类型,例如int,float,char等* 

s.push(item);			*//把item放到栈顶*

s.top();     			*//返回栈顶的元素,但不会删除*

s.pop(); 				*//删除栈顶的元素,但不会返回。在出栈需要进行两步操作,即先top()获得栈*						顶元素,再pop()删除栈顶元素

s.size();				*//返回栈中元素的个数*

s.empty();				*//检查栈是否为空,如果为空,返回true,否则返回false*
队列和queue

队列是基本的数据结构之一,特点是“先进先出”。例如排队,先进队列的先得到服务。
头文件#include<queue>
队列的有关操作:

queue<<Type>Type>q;	//定义队列,Type为数据类型,例如int、float、char等

q.push(item);		//把item放进队列

q.front();			//返回对手元素,但不会删除

q.pop();			//删除队首元素

q.back();			//返回队尾元素

q.size();			//返回元素个数

q.empty():			//检查队列是否为空
优先队列和priority_queue

优先队列,顾名思义就是优先级最高的先出队。它是队列和排序的完美结合,不仅可以存储数据,还可以将这些数据按照设定的规则进行排序。每次的push和pop操作,优先队列都会动态调整,把优先级最高的元素放在前面。
优先队列的有关操作如下:

q.top();//返回具有最高优先级的元素值,但不删除该元素
q.pop();//删除最高优先级元素
q.push();//插入新元素

在STL中,优先队列是用二叉堆来实现的,在队列中push一个数或pop一个数,复杂的都是O(log₂n)。
可以用优先队列对数据排序:设定数据小的优先级高,把所有数push进行优先队列后一个个top出来,就得到了从小到大的排序。其总复杂度是O(nlog₂n)。

链表和list

STL的list是数据结构的双向链表,它的内存空间可以是不连续的,通过指针来进行数据的访问,它可以最高效率地在任意地方删除和插入,插入和删除操作是常数时间的。
list和vector的优缺点正好相反,他们的应用场景不同。

(1) vector:	//插入和删除操作少,随机访问较少。
(2)	 list:		//插入和删除频繁,随机访问较少。
关联式容器

关联式容器包括set、multiset、map、multimap等。

set:			集合,快速查找,不允许重复值。
multiset:		快速查找,允许重复值。
map:			一对一映射,基于关键字快速查找,不允许重复值。
multimap:		一对多映射,基于关键字快速查找,允许重复值。
set

set就是集合。STL的set用二叉搜索数实现,集合中的每个元素只出现一次,并且是排好序的。访问元素的时间复杂度是O(log₂n),非常高效。
set的有关操作:

set<<Type>Type>A;//定义

A.insert(item);//把item放进set

A.erase(item);//删除元素item

A.clear();//清空set

A.empty();//判断是否为空

A.size();//返回元素个数

A.find(k);//返回一个迭代器,指向键值k

A.lower_bound(k);//返回一个迭代器,指向键值不小于k的第一个元素

A.upper_bound(k);//返回一个迭代器,指向键值大于k的第一个元素
map

map是关联容器,它可以实现从键(Key)到值(Value)的映射。map效率高的原因是它用平衡二叉树搜索数来存储和访问。

头文件

#include <map> //注意,STL头文件没有扩展名.h
map的基本操作函数:

 begin()         //返回指向map头部的迭代器

 clear()        //删除所有元素
 
 count()         //返回指定元素出现的次数
 
 empty()         //如果map为空则返回true

 end()           //返回指向map末尾的迭代器

 equal_range()   //返回特殊条目的迭代器对

 erase()         //删除一个元素

 find()          //查找一个元素

 get_allocator() //返回map的配置器

 insert()        //插入元素

 key_comp()      //返回比较元素key的函数

 lower_bound()   //返回键值>=给定元素的第一个位置

 max_size()      //返回可以容纳的最大元素个数

 rbegin()        //返回一个指向map尾部的逆向迭代器

 rend()          //返回一个指向map头部的逆向迭代器

 size()          //返回map中元素的个数

 swap()           //交换两个map

 upper_bound()    //返回键值>给定元素的第一个位置

 value_comp()     //返回比较元素value的函数

2、sort()

STL的排序函数sort()是算法竞赛中最常用的函数之一,它的定义有以下两种:

(1)void sort(RandomAccessIterator first,RandomAccessIterator last);
(2)void sort(RandomAccessIterator first,RandomAccessIterator last,Compare comp);
sort()的比较函数

排序是对比元素的大小。sort()可以用自定义的比较函数进行排序,也可以用系统的4中函数排序,即less()、greater()、less_equal()、greater_equal()。在默认情况下,程序是按从小到大的顺序排序的,less()可不写。

#include<bits/stdc++.h>

using namespace std;

bool my_less(int i,int j) 
{
	return (i<j);//自定义小于
} 

bool my_greater(int i,int j) 
{
	return (i>j);//自定义大于
}

int main()
{
	vector<int>a = {9,8,7,6,1,2,3,4,5}; 
	sort(a.begin(),a.begin()+4);					//对前4个排序,输出6 7 8 9 1 2 3 4 5
	//sort(a.begin(),a.end());						//从小到大排序,输出1 2 3 4 5 6 7 8 9
	//sort(a.begin(),a.end(),less<int>());			//输出1 2 3 4 5 6 7 8 9
	//sort(a.begin(),a.end(),my_less);				//自定义排序,输出1 2 3 4 5 6 7 8 9
	//sort(a.begin(),a.end(),greater<int>());		//从大到小排序,输出9 8 7 6 5 4 3 2 1
	//sort(a.begin(),a.end(),my_greater);			//自定义排序,输出9 8 7 6 5 4 3 2 1
	for(int i = 0 ; i < a.size() ; i++)
		cout << a[i] << " ";
	return 0;
}

相关函数

stable_sort():当排序元素相等时,保留原来的顺序。
partial_sort():局部排序。

3、next_permutation()

STL提供求下一个排列组合的函数next_permutation()。例如3个字符a、b、c组成的序列,next_permutation()能按字典序返回6个组合,即abc、acb、bac、bca、cab、cba。

函数next_permutation()的定义有下面两种形式:

(1)bool next_permutation(BidirectionalIterator first,BidirectionalIterator last);
(2)bool next_permutation(BidirectionalIterator first,BidirectionalIterator last,Compare comp);

返回值:如果没有下一个排列组合,返回false,否则返回true。每执行next_permutation()一次, 就会把新的排列放到原来的空间里。

复杂度:O(n)。

注意,它排列的范围是[first,last),包括first,不包括last。
若使用next_permutation()的时候,初始序列一般是一个字典序最小的序列,如果不是,可以用sort()排序,得到最小序列,然后再使用next_permutation()。

  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小羊努力变强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值