排序
快速排序
1、快速排序
快速排序的基本思想是基于分治法的:设从小到大排序,在待排序表 L[1…n]中任取一个元素pivot作为枢纽(或基准,通常取首元素),通过一趟排序将待排序表划分为独立的两个部分L[1…k-1]和L[k+1…n],使得k左边的元素都小于pivot,右边的元素都大于pivot,则pivot放在了最终位置L[k]处,这个过程叫做一趟快速排序(或一次划分)。然后分别递归地对两个子表重复上述过程,直到每部分内只有一个元素或空为止。
快排的时间复杂度为O(nlog2n),是所有内部排序算法中平均性能最优的排序算法,但是是一种不稳定的排序算法。
算法如下:
/**
*快速排序,确定枢纽的位置,左边值都比枢纽值小,右边都比枢纽大
*@param arr 要排序的数组
*@param low 数组区左端点,默认该值为枢纽
*@param high 数组区间右端点
*@return 返回枢纽最终位置(整个排序的最终位置)
*/
int partition (int arr[], int low, int high){
int pivot = arr[low];
while( low < high ){
while(low < high && arr[high] >= pivot){
high --;
}
arr[low] = arr[high];
while(low < high && arr[low] <= pivot){
low ++;
}
arr[high] = arr[low];
}
arr[low] = pivot;
return low;
}
/**
*快速排序
*@param arr 要排序的数组
*@param low 数组区左端点
*@param high 数组区间右端点
*/
void quick_sort(int arr[], int low, int high){
if(low < high){
int pivot_pos = partition(arr, low, high);
quick_sort(arr, low, pivot_pos - 1);
quick_sort(arr, pivot_pos + 1, high);
}
}
2、基于快速排序,查找第m小的元素
因为快排每次排序确定的枢纽位置都是最终位置,所以边排序边判断枢纽的位置是否为题目要求的位置
/**
*快速排序,确定枢纽的位置,左边值都比枢纽值小,右边都比枢纽大
*先判断枢纽值的位置是否为要查的位置,否则分别再向左、右排序
*@param arr_birth 要排序的数组
*@param low 要排序的数组区间左端点
*@param high 要排序的数组区间右端点
*@param n 第m位置
*@return 返回枢纽值
*/
int quick_sort (int arr[], int low, int high,int m){
int low_tmp = low;
int high_tmp = high;
int pivot = arr[low];
while( low < high ){
while(low < high && arr[high] >= pivot){
high --;
}
arr[low] = arr[high];
while(low < high && arr[low] <= pivot){
low ++;
}
arr[high] = arr[low];
}
arr[low] = pivot;
if(low == m ){
return arr[low];
}else if ( low < m){
return quick_sort(arr, low+1, high_tmp,m);
}else{
return quick_sort(arr, low_tmp, low-1,m);
}
}
2、折半插入排序
折半插入排序仅仅是减少了比较元素的次数,约为O(log2 n),该比较次数与待排序表的初始状态无关,仅取决于表中元素的个数;而元素的移动次数未改变,它依赖于待排序表的初始状态。因此,该排序的时间复杂度为O(n2),但对于数据量不大的排序表,该排序算法往往能表现出很好的性能。
折半插入排序是一种稳定的排序算法。
/**
*折半插入排序,数据量不大时,性能较好且稳定
*@param arr 要排序的数组
*@param n 数组大小
*/
void insert_sort(int arr[] ,int n){
int i, j, low, high, mid;
int tmp;
for(i = 1 ; i < n ; i ++){
tmp = arr[i];
low = 0;
high = i - 1;
while (low <= high){
mid = (low + high) / 2;
if( arr[mid] > tmp ){
high = mid - 1;
}else{
low = mid + 1;
}
}
for(j = i-1; j >= high+1; j --){
arr[j+1] = arr[j];
}
arr[high + 1] = tmp;
}
}