本篇主要记录了排序算法,对于冒泡、选择、插入排序还是很好理解的,不过归并排序、堆排序、快速排序可能就不那么好理解好实现了。
归并排序
题目要求:使用归并排序算法将一个乱序数组进行排序
首先还是梳理一下归并排序是怎么回事,一句话先分再合,接下来看一个例子吧
每次从中间分开数组,直到数组个数为1,然后进行合并。显然,这个过程是递归的思想,哈哈,也许这个显然很不容易(因为递归并不是一个好理解的东西)。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include <iostream> #include <vector> using namespace std; void my_print(vector<int>& v) { for (int i = 0; i < v.size(); ++i) { cout<<v[i]<<" "; } cout<<endl; } void MergeArray(vector<int>& v,int low,int mid,int high,vector<int>& temp) { int i=low; int j=mid+1; int k=0; while(i<=mid && j<=high) { if(v[i]<v[j]) temp[k++]=v[i++]; else temp[k++]=v[j++]; } while(i<=mid) temp[k++]=v[i++]; while(j<=high) temp[k++]=v[j++]; for (i = 0; i < k; i++) { v[low+i] = temp[i]; } } int MergeSort(vector<int>& v,int low ,int high,vector<int>& temp) { int mid=low+(high-low)/2; if(low<high) { MergeSort(v,low,mid,temp); MergeSort(v,mid+1,high,temp); MergeArray(v,low,mid,high,temp); my_print(v); } } int main() { int a[]={4,3,2,1,9,6,8,7}; vector<int> v(a,a+sizeof(a)/sizeof(int)); vector<int> temp(8); MergeSort(v,0,7,temp); return 0; }
|
好了,代码也上了,我们还是来分析一下难搞的递归吧,下面是程序运行的结果。
3 4 9 6 2 1 8 7
3 4 6 9 2 1 8 7
3 4 6 9 2 1 8 7
3 4 6 9 1 2 8 7
3 4 6 9 1 2 7 8
3 4 6 9 1 2 7 8
1 2 3 4 6 7 8 9
其实每一次拆分对应了一次合并,这个递归过程其实就不断的拆分,然后将对应的拆分合并。
堆排序
题目要求:使用堆排序算法将一个乱序数组进行排序。
有如下一位数组,上方的数是数组的下标:
其实数组可以对应一个二叉树(也就是一个堆):
众所周知,最大堆的堆顶一定是这个堆中最大的,那么算法思路如下:
①将数组调整为最大堆
②将堆顶元素(数组第一个值)和堆底元素(数值的最后一个值)交换(也就是把最大的数放到数组的最后一个位置),同时将数组的长度减1
③重复①②(每次都将当前数组最大值放到当前数组最后的位置),直到数值长度为0
这里列出第一次调整堆(也可以当成构建最大堆)的结果:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include <iostream> #include <vector> using namespace std; void HeapAdjust(vector<int>& array,int s,int length) { int temp = array[s]; int child = 2*s+1; while(child < length) { if(child+1 < length&& array[child] < array[child+1]) child++; if(array[s] < array[child]) { array[s] = array[child]; s = child; child = 2*s+1; } else break; array[s] = temp; } } void HeapSort(vector<int>& array,int length) { int i; for(i=(length-1)/2;i>=0;i--) { HeapAdjust(array,i,length); } for(i=length-1;i>0;i--) { int tmp = array[i]; array[i] = array[0]; array[0] = tmp; HeapAdjust(array,0,i); } } int main() { int array[]={3,4,5,1,9,8,6,2,7,10}; vector<int> v(array,array+sizeof(array)/sizeof(int)); HeapSort(v,10); int i; for(i=0;i<10;i++) cout<<v[i]<<" "; cout<<endl; return 0; }
|
快速排序
快排算法实现步骤:
第一步:选择数组首位为基准点
第二步:设立两个指针,一个用于遍历数组,另一个指针m用于指向比基准点小的值应该放的位置
第三步:遍历完数组后,将首位的基准点和最后m指向的值进行交换,返回m。这样一次快排就完成了
第四步:将m作为分界点,将原数组分成两个。重复第二步、第三步,直到数组大小为1,整个快排就结束了 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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> #include <vector> using namespace std; int Find_pos(vector<int>& v,int low,int high) { int m=low; for (int i = low+1; i <= high; ++i) { if(v[i]<v[low]) { swap(v[++m],v[i]); } } swap(v[m],v[low]); return m; } void QuickSort(vector<int>& v,int low ,int high) { if(low<high) { int pos=Find_pos(v,low,high); QuickSort(v,low,pos); QuickSort(v,pos+1,high); } } int main() { int array[]={3,4,5,1,9,8,6,2,7,10}; vector<int> v(array,array+sizeof(array)/sizeof(int)); QuickSort(v,0,9); int i; for(i=0;i<10;i++) cout<<v[i]<<" "; cout<<endl; return 0; }
|