八大排序算法总结
来源:互联网 发布:http 文件 json 上传 编辑:程序博客网 时间:2024/06/06 01:58
算法一:插入排序
将数据依次插入,对于每次新插入的数据,从末尾开始在已排好序的数列中找到其正确的位置,将其后数据从最后一个依次后移,最后插入。若待插入元素与有序序列中某元素相等,则插入在相等元素的后面,故稳定。
代码实现:
void insert_sort(intarray[], intn)
{
int i, j, temp;
for (i = 1; i < n; i++) //i为当前要插入的数据索引,开始时均插在最后
{
temp= array[i];
for (j = i; j > 0&& array[j - 1] > temp; j--) //将i前数据与i比较,后移空位置
array[j] = array[j - 1];
array[j] = temp; //将i放置该放位置
}
}
缺点:共需n趟排序,效率低,并且每次循环只能将数据移动一位
算法二:希尔排序
选择一个增量序列,按照增量序列进行k趟排序,没趟排序将整个待排序的记录序列分割成为m个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时(增量降为1),再对全体记录进行依次直接插入排序, 不稳定。
代码实现:
void shell_sort(intarray[], intn)
{
int i, j, Increment,temp;
for (Increment = n / 2; Increment >0; Increment /= 2) //计算希尔增量,对应k趟排序
for (i = Increment; i< n; i++) //i为要插入的数据索引,开始时均插在子序列最后
{
temp= array[i];
for (j = i; j >=Increment &&array[j - Increment] > temp; j -=Increment)
//将i在子序列中前面数据依次与i比较, 后移空出位置
array[j] = array[j - Increment];
array[j] = temp;
}
}
*** 与直接插入比,多了一层增量循环,j的增值变为增量Increment,故时间复杂度无变化
算法三:选择排序
进行n-1趟排序,每次寻找未排序所有元素的最小值放在已排序序列的最末端,稳定。
代码实现:
void selection_sort(intarray[],int n)
{
int i, j, min;
for (i = 0; i < n - 1; i++) //排序n-1趟,每次寻找i位置上的值
{
min= i;
for (j = i + 1; j< n; j++) //i后数据与min依次比,找应放在i位置上的索引给min
if (array[j] <array[min])
min= j;
if (min != i) //每个位置只交换一次
{
int temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}
}
算法四:冒泡排序
每次比较相邻两元素,若错序则交换,多次遍历,直至无交换,实质上需要排序k-1趟,每次找到未排序元素中的最大值放在已排序序列最前面,稳定。
代码实现:
void bubble_sort(intarray[],int n)
{
int i, j;
for (i = 0; i < n - 1; i++) //排序n-1趟,每次寻找i位置上的值
{
for (j = 0; j< n-i-1; j++) //i后数据与min依次比,找应放在i位置上的索引
if (array[j] >array[j + 1]) //每趟可能需要交换多次
{
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
算法五:归并排序
采用分治思想,对任一序列,分成左右子列,子列内部排序,递归实现,然后用指针移动合并两子列实现归并操作,稳定。
代码实现:
void Merge(intarray[],int tempArr[], int startIndex,intmidIndex, int endIndex)
{
int i = startIndex, j = midIndex + 1, k = startIndex;
while (i != midIndex + 1 && j !=endIndex + 1) //直至有一子列全部排进合并列
{
if (array[i] >array[j])
tempArr[k++] = array[j++];
else
tempArr[k++] = array[i++];
}
while (i != midIndex + 1) //未排完子列剩余元素直接送人合并列
tempArr[k++] = array[i++];
while (j != endIndex + 1)
tempArr[k++] = array[j++];
for (i = startIndex; i <= endIndex; i++) //将合并列放入原序列应有的位置
array[i] = tempArr[i];
}
void mergeSort(intarray[],int tempArr[], int startIndex,intendIndex)
{
int midIndex;
if (startIndex <endIndex)
{
midIndex= (startIndex + endIndex) / 2;
mergeSort(array, tempArr, startIndex, midIndex); //对左子列排序
mergeSort(array, tempArr, midIndex + 1, endIndex); //对右子列排序,注意加1
Merge(array, tempArr, startIndex, midIndex, endIndex); //归并操作合并两子列
}
}
*** 需要提前申请临时空间tempArr[]存放合并列,分治思想降低了时间复杂度,但递归实现提高了空间复杂度
算法六:快速排序--目前最受推崇的排序算法
取序列中任一元素作为枢纽元,将其余元素与该枢纽元比较,分成大小两个集合,等于枢纽元的元素随机分配,递归地对两个集合快速排序。
根据细节不同,有不同的方法,标准算法取第一个数做枢纽元,这样在数组已经有序的情况下,每次划分将得到最坏的结果。一种比较常见的优化方法是随机化算法,即随机选取一个元素作为主元。这种情况下虽然最坏情况仍然是O(n^2),但最坏情况不再依赖于输入数据,而是由于随机函数取值不佳。实际上,随机化快速排序得到理论最坏情况的可能性仅为1/(2^n)。所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度。随机化快速排序的唯一缺点在于,一旦输入数据中有很多的相同数据,随机化的效果将直接减弱。最好的方法是取左端,右端和中间位置上的三个元素的中值做枢纽元。取这3个值的好处是在实际问题中,出现近似顺序数据或逆序数据的概率较大,此时中间数据必然成为中值,而也是事实上的近似中值。万一遇到正好中间大两边小(或反之)的数据,取的值都接近最值,那么由于至少能将两部分分开,实际效率也会有2倍左右的增加,而且利于将数据略微打乱,破坏退化的结构。
代码实现:
int Median3(intarray[], int left, int right)
{
int center = (left +right) / 2;
if (array[left] >array[center]) //将左端,右端,中间三值排序
swap(&array[left], &array[center]);
if (array[left] >array[right])
swap(&array[left], &array[right]);//三者中最小值放左端且无需再判断
if (array[center] >array[right])
swap(&array[center], &array[right]);//三者中最大值放右端且无需再判断
swap(&array[center], &array[right-1]);//三者中中间值放倒数第二个做枢纽元
return &array[right - 1];
}
#define cutoff 3
void QuickSort(intarray[], int left, int right)
{
if (left +cutoff <= right)
{
int pivot = Median3(array,left, right);
int i = left;
int j = right - 1;
while (1)
{
while (array[++i] < pivot) {}//从两侧分别找到错误分组的元素
while (array[--j] > pivot) {}
if (i < j) //若i,j尚未交错
swap(&array[i], &array[j]);
else
break; //当前分组正确
}
swap(array[i], array[right - 1]); //把枢纽元放到中间
QuickSort(array, left, i - 1);
QuickSort(array, i + 1, right);
}
else
InsertionSort(array + left, right - left + 1);//对于小数组,插入排序更合适
}
*** 与归并相比,同样是递归,可是分成的两个子问题并不一定相等(隐患),但分成两组是在适当的位置进行且非常有效,故比递归更快。
未完待续。。。
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 八大排序算法总结
- 【设计模式】代理模式
- Wireless Network(POJ 2236)
- OpenCV教程 之 边缘检测函数:Canny、Sobel、Scharr(C++)
- java中有关Frame背景的设置总结
- springmvc常用注解标签详解
- 八大排序算法总结
- MySQL忘记密码
- webrtc百度网盘下载与windows平台编译错误解决
- Speech Patterns
- scrapy入门
- RabbitMQ官方中文入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)
- 【C语言】移位运算符、位运算符、逻辑运算符
- 51Nod-1091-线段的重叠
- rhel与aix中,fsck -f的区别