算法中最基本的便是查找和排序算法了,和几个已经找工作的师兄师姐交流,面试时经常会问到排序算法和相关的问题。经常有面试官要求现场写出一种排序算法的代码。如果我们说我们会冒泡算法,,未免显得有些low,所以今天就想总结一些常用的排序算法,以及代码实现。
一、冒泡排序。
虽然冒泡排序是大学学过的最简单的排序之一,但是如果你真的想不起来你会什么排序算法,拿冒泡排序来救场也是ok的。而且算法的本质都是一通则全通。
基本思想:依次比较相邻的两个数,将小数放在前面,大数放在后面,即通过与相邻元素的比较把小的数交换到最前面。
举个例子:对无序序列 3 1 5 7 4进行冒泡排序。首先从后向前冒泡,先将 7 4 比较,把4放在7前面,这时序列变成 3 1 5 4 7。然后对5 4 排序,将4 交换到5 前面,这时序列变成 3 1 4 5 7。再对1 4排序,不用交换,序列仍为 3 1 4 5 7。这时交换过程还没结束,再对 3 1 排序,将1交换到最前面,这时序列变成 1 3 4 5 7(一次冒泡就完成了)。此时就把这个序列的最小值1交换到了数组的最前面。然后依次对后面序列再次冒泡排序,排序的时间复杂度为O(n^2)-------这时最坏的情况下的时间复杂度。
对于n位的数列则有比较次数为 (n-1) + (n-2) + ... + 1 = n * (n - 1) / 2
时间复杂度: 定义:一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。
排序算法的时间复杂度O(n^2)指的是数量级。
举个例子:如果n=10000,那么n*(n-1)/2=(n^2-n)/2。代入的话10000*(10000-1)/2=(100000000-10000)/2.相比于10^8来说,10000可以忽略不计了,结果为0.5*(n^2).忽略掉T(n)中的常量、低次幂和最高次幂的系数.也就是不计入0.5.所以时间复杂度就为O(n^2).
#include <iostream>
using namespace std;
void BubbleSort(int list[],int n);
int main()
{
int a[]={2,4,6,8,0,1,3,5,7,9};
BubbleSort(a,10);
for(int k=0;k<10;k++)
cout<<a[k]<<" ";
return 0;
}
void BubbleSort(int list[],int n)
{
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(list[j]>list[j+1])
std::swap(list[j],list[j+1]);
}
}
}
2、选择排序
从当前未排序的整数中找一个最小的整数,将它放在已排序的整数列表的最后。
要点:选择排序选最小的,往左边选
#include <iostream>
using namespace std;
void SelectSort(int *list, const int n);
int main()
{
int x[]={1,3,5,7,0,2,4,6,8};
SelectSort(x,10);
for(int k=0;k<10;k++)
{
cout<<x[k]<<endl;
}
return 0;
}
void SelectSort(int *list,const int n)
{
for(int i=0;i<n;i++)
{
int min=i;
for(int j=i+1;j<n;j++)
{
if(list[j]<list[min])
min=j;
}
swap(list[i],list[min]);
}
}
3顺序查找
没有排序的数据,只能顺序查找,顺序查找的缺点,速度慢,不适合以万计的大数据的查找
但对于一些数量不多,但又没有】排序的数组,采用顺序查找也是一种比较简单方便的方法
#include <iostream>
using namespace std;
int SequentialSearch(int *a,const int n,const int x);
int main()
{
int m[]={2,4,6,8,0,1,3,5,7,9};
int a;
int num=7;
a=SequentialSearch(m,10,num);
if(a==-1)
cout<<"no find"<<endl;
else
cout<<"zai m["<<a<<"]li zhaodao"<<num<<endl;
return 0;
}
int SequentialSearch(int *a,const int n,const int x)
{
int i;
for(i=0;i<n;i++)//把数组中每个数进行检查
{
if(a[i]==x)
return i;
}
if(i==n) return -1;
}
4、折半查找(二分查找)
数据必须先排序。速度快。
2^20=100万(就是1M);
2^30=10亿(就是1G);
也就是100万个数据,需要20次就可以找到;
#include <iostream>
using namespace std;
int BinarySearch(int *a,const int x,const int n);
int main()
{
int x[]={1,2,3,4,5,6,7,8,9,10};
int b;
int num;
num=7;
b=BinarySearch(x,num,10);
if(b<0)
cout<<"Do not find"<<endl;
else
cout<<"在x["<<b<<"]找到"<<num<<endl;
return 0;
}
int BinarySearch(int *a,const int x,const int n)
{
int low,high,mid;//假设数据是竖着放的,
low =0,high =n-1;
while(low<=high)
{
mid =(low+high)/2;
if(a[mid]==x)
return mid;
else if(a[mid]<x)
low = mid+1;
else if(a[mid]>x)
high=mid-1;
}
return -1;
}
int BinSearch(int *a, const int x, const int n)
{
int left =0,right=n-1;//也有横着放的,可以用left,right
while(left<=right)
{
int middle=(left+right)/2;
if(x<a[middle]) right= middle-1;
else if(x>a[middle]) left=middle+1;
else return middle;
}
}
5、插入排序
有一个已经有序的数据序列,要求在这个已经拍好的数据序列中插入一个数,但要求插入后此数据仍然有序,这个时候需要用到一种新的排序方法---插入排序法。
其基本操作就是将一个数据插入到已经拍好的有序数据中,从而得到一个新的,个数加1 的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)
若是升序排序,每次插入一个数据就要与他前面的数据进行比较
示例程序如下:
#include <iostream>
using namespace std;
void InsertionSort(int *a,int n);
int main()
{
int x[]={2,4,6,8,0,1,3,5,7,9};
InsertionSort(x,10);
for(int i=0;i<10;++i)
cout<<x[i];
return 0;
}
void InsertionSort(int *a, int n)
{
int in,out;//开始时out=0这个人已经出去了
for(out=1;out<n;++out)
{
int temp=a[out];
in=out;
while(in>0&&a[in-1]>=temp)
{
a[in]=a[in-1];
--in;
}
a[in]=temp;
}
}
当数组不仅仅是整型的时候,这时引入模板类,通过调用模板类来对数组进行排序,
在下例程序中还通过引入InsertSort_2来减少条件的判断,从而优化程序使其更快。
#include <iostream>
using namespace std;
template<class T>
void InsertionSort(T *a,int n);
template<class T>
void InsertionSort_2(T *a,int n);
template<class T>
void Insert(const T&e,T*a,int i);
int main()
{
double x[]={2.5,4.3,6,8,0,1,3,5,7,9};//当数组类型多种多样时,有可能是浮点型等等,就可以考虑做成模板
int y[]={0,2,4,6,8,1,0,3,5,7,9};//这里用到一个小技巧,第一个数据a[0]置0 仅仅当作排序使用,不能保存原始数据
InsertionSort(x,10);
InsertionSort_2(y,10);
for(int i=1;i<=10;++i)
cout<<y[i];
return 0;
}
template<class T>
void InsertionSort(T *a, int n)
{
int in,out;//开始时out=0这个人已经出去了
for(out=1;out<n;++out)
{
int temp=a[out];
in=out;
while(in>0&&a[in-1]>=temp)
{
a[in]=a[in-1];
--in;//依次与前一个数据进行比较
}
a[in]=temp;
}
}
template<class T>
void InsertionSort_2(T *a,int n)
{
for(int j=2;j<=n;++j)
{
T temp=a[j];
Insert(temp,a,j-1);
}
// a[0]=temp;//a[0]用来保存排序使用,不能保存原始数据
// int i=j-1;
// while(temp<a[i])
// {
// a[i+1]=a[i];
// i--;
// }
// a[i+1]=temp;
}
template<class T>//把上面注释部分又拆分成了一个模板函数
void Insert(const T&e,T*a,int i)
{
a[0]=e;
while(e<a[i])
{
a[i+1]=a[i];
i--;
}
a[i+1]=e;
}
这一节内容有些长,下一篇贴快速排序算法的等等。。。。。