排序算法
插入排序(Insertion Sort)
对于nums[n]数组
因为a[0]已自动排序,我们遍历1~ n-1,对i∈[1,n-1]的a[i]进行遍历依次做插入排序。记a[i]=temp。对每一个a[i],我们对j=i ~ 1进行遍历,若a[j-1]>temp则位置顺延(a[j]=a[j-1]).
*算法分析
时间:O(n2)
空间:O(1)
性质:stable
*code
1 2 3 4 5 6 7 8 9 10 11
| void insertionsort(int nums[],int len) { for(int i=1;i<len;i++){ int temp=nums[i]; int j; for(j=i;j>0&&nums[j-1]>temp;j--){ nums[j]=nums[j-1]; } nums[j]=temp; } }
|
希尔排序(Shell Sort)
划分数组成为若干子数组,对若干子数组进行插入排序
*算法分析
时间:O(n2),好的增量可做到O(n23).
空间:O(1)
性质:unstable
*code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void shellsort(int nums[],int len) { int increment; for(increment=len/2;increment>0;increment/=2){ for(int i=increment;i<len;i++){ int temp=nums[i],j; for(j=i;j>=increment;j-=increment){ if(temp<nums[j-increment]){ nums[j]=nums[j-increment]; }else{ break; } } nums[j]=temp; } } }
|
冒泡排序(bubble sort)
通过交换,使较小的数浮到前位
*算法分析
时间:O(n2)
空间:O(1)
性质:stable
*code
1 2 3 4 5 6 7 8 9 10 11 12 13
| void bubblesort(int nums[],int len) { int flag=1; for(int i=1;i<len&&flag==1;i++){ flag=0; for(int j=0;j<len-i;j++){ if(nums[j]>nums[j+1]){ flag=1; swap(nums[j],nums[j+1]); } } } }
|
快速排序(quick sort)
选取枢纽元,小于枢纽元和大于枢纽元的部分进行分治排序。
1.枢纽元的选取
选首位元素:对于预排序和反序的序列有高的复杂度O(n2)
*三数中值分割:
选左、中、右三位的中位数作主元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int median3(int nums[],int left,int right) { int center=(left+right)/2; if(nums[left]>nums[center]){ swap(nums[left],nums[center]); } if(nums[left]>nums[right]){ swap(nums[left],nums[right]); } if(nums[center]>nums[right]){ swap(nums[center],nums[right]); } swap(nums[center],nums[right-1]); return nums[right-1]; }
|
2.利用循环完成对序列的分割,即小于主元和大于主元两部分
3.递归分治
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| void Qsort(int nums[],int left,int right) { int i,j,pivot;
pivot=median3(nums,left,right); i=left+1; j=right-2; if(i>j){ return; }
while(1){ while(nums[i]<pivot){ i++; } while(nums[j]>pivot){ j--; } if(i<j){ swap(nums[i],nums[j]); }else{ break; } }
swap(nums[i],nums[right-1]); Qsort(nums,left,i-1); Qsort(nums,i+1,right); }
|
*算法分析
时间:平均O(nlogn)
空间:O(logn)
性质:unstable
选择排序(select sort)
选定一个元素作为基点,遍历后方元素,寻找最小的与基点交换位置
*算法分析
时间:O(n2)
空间:O(1)
性质:unstable
*code:
1 2 3 4 5 6 7 8 9 10 11 12
| void selectsort(int nums[],int len) { for(int i=0;i<len;i++){ int j=i; for(int k=i+1;k<len;k++){ if(nums[k]<nums[j]){ j=k; } } swap(nums[i],nums[j]); } }
|
堆排序(heap sort)
利用堆性质的排序。
1.堆的操作,向下调整:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void downadjust(int nums[],int start,int end) { int record=nums[start],j; for(j=2*start+1;j<=end;j=j*2+1){ if(j<end&&nums[j]<=nums[j+1]){ j++; } if(nums[j]<=record){ break; } nums[start]=nums[j]; start=j; } nums[start]=record; }
|
2.排序步骤
对于升序,我们选择大根堆。大根堆父节点元素值一定大于等于子节点元素值,根节点是堆的最大值。
首先对序列建堆,我们使用向下调整。从最后一个元素的父节点开始。
建堆完成后,我们要做deletemax并取根节点交换到末位置,通过向下调整以完成deletemax.
1 2 3 4 5 6 7 8 9 10
| void heapsort(int nums[],int len) { for(int i=(len-1)/2;i>=0;i--){ downadjust(nums,i,len-1); } for(int i=len-1;i>0;i--){ swap(nums[0],nums[i]); downadjust(nums,0,i-1); } }
|
*算法分析
时间:O(nlogn)
空间:O(1)
性质:unstable