C/C++算法
本文为网上整理实测。
一、查找算法
1.二分查找
(1)概述
核心思想:将元素分成两部分,如果目标大于中间元素,则重新在右边查找,反之亦然。
要求:有序数组
时间复杂度:O(log2n)
(2)代码实例
#include <iostream>
#include <vector>
using namespace std;
void show(vector<int> &v)
{
for(int i = 0; i < v.size(); i++) cout<< i << '\t'; cout<<endl;
for(auto x: v) cout<< x << '\t'; cout<<endl;
}
int binarySearch(vector<int> v,int target)
{
int left = 0;
int right = v.size() - 1;
while(left <= right)
{
int mid = (left + right) / 2;
if(target == v[mid])
return mid;
else if(target > v[mid])
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
return -1;
}
int main()
{
vector<int> v = {1,2,4,5,7,9,12,13,23,45,46,51,58};
show(v);
int x = 0;
while(cin>>x)
{
int site = binarySearch(v,x);
cout<<"site: "<< site << endl;
}
return 0;
}
2.插值查找
(1)概述
基本思想:基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。
也就是将上述的比例参数1/2改进为自适应的,根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。
二分查找中查找点计算如下:
mid=(low+high)/2, 即mid=low+1/2*(high-low);
将查找的点改进为:
int mid = left + (right - left) * (target - v[left]) / (v[right] - v[left]);
二、排序算法
数据交换:
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
1.冒泡排序(Bubble sort)
(1)概述
核心思想:遍历N次,每次遍历一次将 最大的数放 “末尾”,排好的不参与遍历。
时间复杂度:O(n²)
效率分析:最坏(逆序)和 最好都是 O(n²),因为比较的次数没有减少。是稳定的。
空间复杂度:O(1)
(2)代码实例
#include <iostream>
#include <vector>
using namespace std;
void swap(int &a,int &b){ int s = a;a = b; b = s;}
vector<int> bubble_sort(vector<int> v)
{
int n = v.size();
for(int i = 0;i < n;i++)
{
for(int j = 1;j < n-i; j++)
{
if(v[j-1] > v[j])
swap(v[j-1],v[j]);
}
}
return v;
}
void show(vector<int> v)
{ for(int i = 0; i < v.size(); i++) { cout<<v[i]<<" ";}cout<<endl;}
int main()
{
vector<int>v;
v.push_back(6);v.push_back(9);v.push_back(4);v.push_back(8);
v = bubble_sort(v); show(v);return 0;
}
2.选择排序
(1)概述
核心思想:从未排序的序列中选出一个最小的,放到左边已排序的末尾。
时间复杂度:O(n2),最稳定的排序算法之一
空间复杂度:O(1)
(2)代码实例
#include <iostream>
#include <vector>
using namespace std;
inline void swap(int &a,int &b) { int tmp = a; a = b; b = tmp; }
void show(vector<int> v) { for(auto x: v) cout<< x << " "; cout<<endl; }
vector<int>& select_sort(vector<int> &v)
{
int n = v.size();
for(int i = 0; i < n - 1; i++) // insert sorted array tail
{
int minsite = i;
for(int j = i + 1; j < n; j++) // find min
{
if(v[j] < v[minsite])
minsite = j;
}
swap(v[i],v[minsite]);
}
return v;
}
int main()
{
vector<int> v = {6,3,5,7,2,8,4,1,5,9,1};
show(v);
v = select_sort(v);
show(v);
return 0;
}
3.快速排序
快排1
快排2
(1)概述
核心思想:选择一个基准值,将小于基准值的放左边,大的放右边;以后采用递归的方式对左右两边做相同操作(分治法)
时间复杂度:平均O(NlogN),最差和冒泡排序一样O(N2)(降序的时候)
空间复杂度:
其实这个空间复杂度不太好计算,因为有的人使用的是非就地排序,那样就不好计算了(因为有的人用到了辅助数组,所以这就要计算到你的元素个数了);我就分析下就地快速排序的空间复杂度吧;
首先就地快速排序使用的空间是O(1)的,也就是个常数级;而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据;
最优的情况下空间复杂度为:O(logn) ;每一次都平分数组的情况
最差的情况下空间复杂度为:O( n ) ;退化为冒泡排序的情况
(2)代码实例
#include <iostream>
#include <vector>
using namespace std;
inline void swap(int &a, int &b) { int tmp = a;a = b;b = tmp; }
void show(vector<int> &v) { for(auto x: v) cout<< x <<" "; cout<<endl; }
void quicksort(vector<int> &v,int left,int right)
{
if(left >= right)
return;
int base = v[left];
int i = left;
int j = right;
while(i < j)
{
while(v[j] >= base && i < j)
j--;
while(v[i] <= base && i < j)
i++;
if(i < j)
swap(v[i],v[j]);
}
swap(v[left],v[i]);
quicksort(v,left,i-1);
quicksort(v,i+1,right);
}
int main()
{
vector<int> v = {6,3,5,9,2,8,10,1,4,13,11};
show(v);
quicksort(v,0,v.size()-1);
show(v);
return 0;
}