常用排序算法总结
稳定性:相同数据,排序后,相同数据的相对位置未发生变化,即为稳定
冒泡排序
思想:
通过重复遍历待排序的数列,比较每对相邻元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素为止。遍历结束后,会将元素中较大的值先排到数列后面。
代码:
void bubbleSort(int a[],int len)
{
int i,j;
for(j = len - 1;j > 0;--j)
{
for(i = 0;i < j;++i)
{
if(a[i] > a[i + 1])
{
int t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
}
}
}
}
时间复杂度:
O(n^2)
排序算法的稳定性:
稳定
选择排序
思想:
首先在未排序的序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾
代码:
void choiceSort(int a[],int len)
{
int i,j;
for(i = 0;i < len - 1;++i)
{
for(j = i + 1;j < len;++j)
{
if(a[i] > a[j])
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
}
时间复杂度
O(n^2)
排序算法的稳定性
不稳定
插入排序
思想:
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入
代码:
void insertSort(int a[],int len)
{
int i,j;
for(i = 1;i < len;++i)
{
int t = a[i];
j = i;
while(j > 0 && a[j - 1] > t)
{
a[j] = a[j - 1];
--j;
}
a[j] = t;
}
}
时间复杂度
O(n^2)
排序算法的稳定性
稳定
快速排序
思想
把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。从数列中挑出一个元素,称为“基准”(pivot)。重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。递归地将小于基准值元素的子数列和大于基准值元素的子数列排序。
代码:
void qSort(int *begin,int *end)
{
if(begin >= end)
{
return;
}
int *p = begin;
int *q = end;
int t = *begin;
while(p < q)
{
while(p < q && *q >= t)
{
--q;
}
while(p < q && *p <=t)
{
++p;
}
swapNumbers(p,q);
}
swapNumbers(begin,p);
qSort(begin,p - 1);
qSort(p + 1,end);
}
时间复杂度
O(nlogn)
排序算法的稳定性
不稳定
二分查找
思想:
通过将目标值与数组中间元素的值进行比较,从而减半搜索范围,直到找到目标值或搜索范围为空
代码:
int bianaryFinf(int a[],int len,int n)
{
bubbleSort(a,len);
int i,j;
int begin = 0;
int end = len - 1;
int mid;
for(i = begin;i < end;++i)
{
mid = (begin + end) / 2;
if(n > mid)
{
begin = mid + 1;
}
else if(n < mid)
{
end = mid - 1;
}
else
{
break;
}
if(begin <= end)
{
return i;
}
else
{
return -1;
}
}
}
二分查找的前提:
数列必须有序
时间复杂度
O(logn)