插入排序:
1).直接插入排序:
假设当前排序到了第i个元素arr[i],则此时i左侧[0,i-1]已经有序,对于arr[i]来说,如果arr[i]>=arr[i-1],则不用排序,直接进入[i+1];否则要在左侧有序表中找到一个合适的位置j令arr[j]<=arr[i]<arr[j+1]。
每一趟插入排序,令当前有序表的长度增加1,直至有序长度等于数组长度。
class Solution { public: void InsertSort(vector<int>& arr){ if(arr.empty()) return; for(int i=1;i<arr.size();i++) { if(arr[i]<arr[i-1]) { int tmp=arr[i]; arr[i]=arr[i-1]; int j=i-2; for(;j>=0&&arr[j]>tmp;j--) arr[j+1]=arr[j]; arr[j+1]=tmp; } } return; } };
2).折半插入排序:
和普通的直接插入排序相比,折半插入排序利用了左侧有序表的特性,利用折半查找减少了查询次数,但移动次数仍然未改变。
class Solution { public: void BInsertSort(vector<int>& arr){ if(arr.empty()) return; for(int i=1;i<arr.size();i++) { int low=0,high=i-1; while(low<=high) { int mid=(low+high)/2; if(arr[mid]>arr[i]) high=mid-1; else low=mid+1; } int tmp=arr[i]; for(int j=i-1;j>=high+1;j--) arr[j+1]=arr[j]; arr[high+1]=tmp; } } };
3).希尔排序:
直接插入排序与折半排序都没有实际上减少移动次数,折半排序优化的是比较次数。
希尔排序的思想在于:
如果一个序列是正序的,则对它进行排序只用比较n-1次,而不用移动。因此,如果对于某个待排点i来说,如果i左侧的数组能够基本有序(不是完全有序),则它移动的次数将减少。
希尔排序每一趟排序中,根据增量将序列分为若干组,每一组进行一个直接插入排序,这样每一组都是有序的,再将他们组合起来,也就是说,每一组都将这组的数据小的往前置顶,大的往后置后,则合并起来时相对整个数组来说,它的小数据集中到了前段,大数据集中到了后端,尽管不同的子组间的大小没有确定,但对于数组整体来说,它比这一趟希尔排序前变得更有序了。
等到下一趟排序时,减小增量。减小增量代表在上一趟希尔排序的相对有序的基础上重整上一趟排序时子组间的相对大小。
这样,每进行一趟希尔排序,数组的有序情况得到一定改善,直到最后增量为1时,相对来说比最初的数组的有序性更强了,在进行一次完整的直接插入排序,这样减少了插入过程中的移动次数。
class Solution { public: void ShellSort(vector<int>& arr) { vector<int> dk; dk.push_back(5); dk.push_back(3); dk.push_back(1); for(int i=0;i<dk.size();i++) SortCore(arr,dk[i]); } void SortCore(vector<int>&arr,int dk) { for(int i=dk;i<arr.size();i++) { if(arr[i]<arr[i-dk]) { int tmp=arr[i]; int j=i-dk; for(;j>=0&&arr[j]>tmp;j=j-dk) arr[j+dk]=arr[j]; arr[j+dk]=tmp; } } } };
原文地址:https://www.cnblogs.com/lxy-xf/p/11326302.html
时间: 2024-11-08 21:35:59