直接插入排序 for-if-for
假定数组前面有序,将待排序的部分逐个插入前面有序数组中
例如 :
{3,2,1,8,5}
按从小到大顺序排序,先确定3的顺序
{[3],2,1,8,5}
再将2插入前面有序中,则前面的3需要移动位置,排好后即:
{[2],[3],1,8,5}
……
{[1],[2],[3],[5],[8]}
//插入排序
void InsertSort(int A[], int length){
int temp,i,j;
for( i = 1;i < length;i++){
if(A[i]<A[i - 1]){
temp = A[i]
for( j = i - 1; A[j] > temp;j--){//和temp比较
A[j + 1] = A[j];
}
A[j + 1] = temp;//最后一轮j--,所以这里是A[j + 1]
}
}
}
冒泡排序 for-for-if
两两对比交换顺序,每一轮冒出最小/最大的值
例如 :
{3,2,1,8,5}
冒最大数字:从前往后交换
23185->21385->21358
冒最小数字:从后向前交换
32158->31258->13258
//冒泡排序
void BubbleSort(int A[], int length){
for(int j = 0; j < length ;j++){//控制外循环
for(int i = length - 1; i > 0;i--){ //一轮排序-内层循环 i>0可以改进为i>j ,减少对比次数
if(A[i] < A[i-1]){
int temp = A[i - 1];
A[i - 1] = A[i];
A[i] = temp;
}
}
}
}
快速排序 while
快速排序是基于分治算法的
其思想是选择一个待确定参照located(一般是选择待排序的数组的第一位)确定其所在的数组的位置
例如
{3,2 ,1,5,8}
将3作为参照,其排完序的位置应该在第三位{3,2,1,5,8}
其分为located、low、high
located<=high 不交换 high–
located>=low 不交换 low++
当low=high时 结束
//快速排序
void QuickSort(int A[],int low,int high){
int i,j,located,t;
i = low;
j = high;
located = A[low];
if(low>high)
return;
while(i != j){
while(i < j && located <= A[j])
j--;
while(i < j && located >= A[i])
i++;
if(i < j){//内部交换位置
t = A[i];
A[i] = A[j];
A[j] = t;
}
}
A[low] = A[i];//located的确定位置
A[i] = located;
QuickSort(A,low,i-1);
QuickSort(A,i+1,high);
}
选择排序 for-for-if-if
遍历数组,选择最小/最大,然后交换位置
例如 :
{3,2,1,8,5}
{1,2,3,8,5}>>{1,2,3,5,8}
/******
min作数组下标 A[min]才是最小值
****/
//选择排序
void SelectSort(int A[] , int length){
int min = 0,i,j;
for( j = 0 ; j < length ; j++){
min = j;
for (i = j + 1 ; i < length ; i++){
if(A[i] < A[min]){
min = i;
}
}
if(i != min){
int temp = A[j];
A[j] = A[min];
A[min] = temp;
}
}
}
归并排序
归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
该算法同样采用分治法,分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之
待排序数组
{[3],[2],[1],[5],[8],[7]}
数组下标 0 1 2 3 4 5
3 2 1 5 8 7
递归分组
3 2 1|| 5 8 7
3 2 || 1 || 5 8 || 7
[3],[2],[1],[5],[8],[7]
其程序思想大概是利用递归将有序数组分组(将问题分解成逐个小问题),再执行归并操作(解决小问题)
程序执行过程:
第一次归并
{1,2} {3} {5,7} {8}
第二次归并
{1,2,3} {5,7,8}
第三次归并
{1,2,3,5,7,8}
归并的过程可看成一颗二叉树,可通过探讨二叉树来分析算法的复杂度
//归并排序
void Merge(int A[],int low,int high){
int *B = (*int)malloc((high - low + 1)*sizeof(int));
int mid = (low + high)/2;
int i = low;
int j = mid + 1;
int k = 0;
for(k = low;k <= high ; k++){
B[k] = A [k];
}
for(k = i; i <= mid && j <= high;k++){
if(B[i] <= B[j]){
A[k] = B[i++];
}
else
A[k] = B[j++];
}
while(i <= mid) A[k++] = B[i++];
while(j <= high) A[k++] = B[j++];
free(B);
}
void MergeSort(int A[],int low,int high){
if(low < high){
int mid = (low + high)/2;
MergeSort(A,low,mid);
MergeSort(A,mid + 1,high);
Merge(A,low,high);
}
}