排序算法代码总结

xiaoxiao2021-02-28  83

#include<iostream> #include<vector> #include<math.h> using namespace std; class sort { public: //交换两个变量的值 void swap(int &a,int &b) { int temp = a; a = b; b = temp; } //冒泡算法1:固定一个,让其替换为最小的值 时间复杂度O(n^2) //稳定性:稳定 void BubbleSort0(vector<int> &L) { for(int i = 0; i < L.size();++i) for(int j = i +1; j < L.size();++j) { if(L[i] > L[j]) swap(L[i],L[j]); } } //冒泡算法2:正宗的冒泡排序算法,两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。时间复杂度O(n^2) void BubbleSort(vector<int> &L) { for(int i = 1; i < L.size();++i) for(int j = 0; j < L.size() - i;++j) { if(L[j] > L[j+1]) swap(L[j + 1],L[j]); } } //冒泡算法3:冒泡的改进算法 ,增加FLAG标志位 时间复杂度O(n^2),但是性能会好 void BubbleSort2(vector<int> &L) { for(int i = 1; i < L.size();++i) { bool flag = true; for(int j = 0; j < L.size() - i;++j) { if(L[j] > L[j+1]) { swap(L[j + 1],L[j]); flag = false; } } if(flag) break; } } //选择排序:基本思想为一趟在n - i + 1个记录中选取关键字最小的记录作为有序的第i个记录。交换的次数少了,交换需要的时间比较大 //交换的次数少了,性能优于冒泡排序 时间复杂度O(n^2) //稳定性:稳定 void SeleteSort(vector<int> &L) { for(int i = 0 ;i < L.size() ; ++i) { int minIndex = i; for(int j = i + 1; j < L.size(); ++j) { if(L[minIndex] > L[j]) minIndex = j; } if(minIndex != i) swap(L[i],L[minIndex]); } } //直接插入排序:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。时间复杂度O(n^2) //稳定性:稳定 void InsertSort(vector<int> &L) { int temp; //有序表是一点一点增加的,刚开始只有一个元素,则循环是从元素下标1开始的 //有序表区间为[0,i - 1] j下标是要和temp替换的那个 for(int i = 1; i < L.size() ; ++i) { if( L[i] < L[i - 1] ) { temp = L[i]; int j = i - 1; while(j >= 0 && temp < L[j]) { L[j + 1] = L[j]; --j; } L[j + 1] = temp; } } } //希尔排序:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序, //然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。 //因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。 //时间复杂度:O(nlogn)~O(n^2) //稳定性:不稳定 void ShellSort(vector<int> &L) { int increment = L.size(); while( increment > 1 ) { increment = increment/3 + 1; //关于增量序列的选择,目前还是数学难题,迄今为止没有人能够找到好的增量序列 //把这个L分成increment个子序列了,下面是对每个子序列进行插入排序 for(int i = 0;i < increment; i++) { //每个子序列的插入排序,原理同上 for( int j = i + increment; j < L.size(); j +=increment) { if(L[j] < L[j - increment]) { int temp = L[j]; int k = j - increment; while(k >= 0 && temp < L[k]) { L[k + increment] = L[k]; k -=increment; } L[k + increment] = temp; } } } } } //堆排序: /* 完全二叉树: 如果从下标从1开始存储,则编号为i的结点的主要关系为: 双亲:下取整 (i/2) 左孩子:2i 右孩子:2i+1 如果从下标从0开始存储,则编号为i的结点的主要关系为: 双亲:下取整 ((i-1)/2) 左孩子:2i+1 右孩子:2i+2 堆:堆是具有特殊性质的二叉树,特殊性质指的是: 每个节点的值都大于或等于其左右孩子结点的值,称为大顶堆; 每个节点的值都小于或等于其左右孩子结点的值,成为小顶堆。 思想:1.将待排序的序列构成一个大顶堆(以大顶堆为例); 2.将堆顶的根结点与末尾元素交换; 3.将剩下的n-1个序列重新构建成一个堆; 返回第2步循环 时间复杂度:O(nlogn) 稳定性:不稳定 */ //对每个非叶结点,需要进行调整成为堆,顺序为:从下往上,从右到左 void HeapAdjust(vector<int> &L,int s,int m) { int temp = L[s]; for(int j = 2 * s + 1;j <= m - 1;j = 2 * j + 1) //沿关键字较大的孩子结点向下筛选 { if(j < m - 1 && L[j] < L[j + 1]) ++j; //j为关键字中较大的记录下标 if(temp >= L[j]) break; L[s] = L[j]; s = j; } L[s] = temp; } void HeapSort(vector<int> &L) { for(int i = ceil(L.size()/2.0); i >= 0; i--) { HeapAdjust(L,i,L.size()); } swap(L[0],L[L.size() - 1]); for(int i = L.size();i > 1 ;i--) { HeapAdjust(L,0,i ); swap(L[0],L[i - 1]); } } //归并排序 先递归的分解数列,再合并数列就完成了归并排序。 // 时间复杂度:O(nlogn) // 稳定性:稳定,但是比较占内存,因为要递归 //归并排序递归版 //合并数组,注意下标指针,并创建一个临时数组 void Merge(vector<int> &A,int l,int mid,int r) { vector<int> C(r - l + 1,0); int i = l; int j = mid + 1; int m = mid,n = r; int k = 0; while(j <= n && i <= m) { if(A[i] > A[j]) C[k++] = A[j++]; else C[k++] = A[i++]; } while(i <= m) { C[k++] = A[i++]; } while(j <= n) { C[k++] = A[j++]; } for(int i = 0;i < k;i++) A[l + i] = C[i]; } //拆分与合并排序 void SplitMerge(vector<int> &D,int l,int r) { if(l < r) { int mid = (l + r) / 2; SplitMerge(D,l,mid); //左边有序 SplitMerge(D,mid + 1,r); //右边有序 Merge(D,l,mid,r); //将左右合并为一个有序序列 } } void MergeSort(vector<int> &L) { SplitMerge(L,0,L.size() - 1); } //归并排序非递归版,直接写在一个函数中, void MergeSort2(vector<int> &L) { int size = 1,l,mid,r; //size为间隔,l,mid,r分别为左中右指针 while(size < L.size()) { l = 0; //左指针为0 while( l + size < L.size() ) { mid = l + size - 1; r = mid + size; if( r > L.size() - 1 ) r = L.size() - 1; Merge(L,l,mid,r); l = r + 1; } size *= 2; } } //快速排序:通过一趟排序将待排序记录分割成独立的两部分,其中一部分的关键字均比另一部分的关键字小,则可分别对这两部分继续进行排序,以达到整个序列有序的目的。 // 算法时间复杂度:O(nlogn) // 稳定性:不稳定 int Partition(vector<int> &L,int l,int r) { int midKey = L[l]; int keyIndex = l; while(l < r) { //先从右边按顺序开始找一个数比midKey小,再从左边按顺序找一个比midKey大 ,左边和右边的指针分别+1,-1 while(l < r && L[r] >= midKey) r--; //从右边开始找比midKey小的数,如果找到则退出,L【r】即为当前比midKey小的数 swap(L[l],L[r]); //交换他们的数值 keyIndex = r; while(l < r && L[l] < midKey) l++; swap(L[l],L[r]); //交换他们的数值 keyIndex = l; } return keyIndex; } void Qsort(vector<int> &L,int l,int r) { if(l < r) { int keyIndex = Partition(L,l,r); Qsort(L,l,keyIndex - 1); Qsort(L,keyIndex + 1,r); } } void QuickSort(vector<int> &L) { Qsort(L,0,L.size() - 1); } //快速排序简洁版本 void quickSort(vector<int> &L,int l,int r) { if(l >= r) return; int left = l; int right = r; int midKey = L[l]; while(left < right) { while(left < right && L[right] >= midKey) right--; L[left] = L[right]; while(left < right && L[left] <= midKey) left++; L[right] = L[left]; } L[left] = midKey; quickSort(L,l,left - 1); quickSort(L,left + 1,r); } }; int main() { sort *p= new sort; int A[10] = {6,9,5,3,8,7,1}; vector<int> L(7,0); for(int i = 0;i < L.size();++i) L[i] = A[i]; p->MergeSort2(L); cout << endl; for(int i = 0;i < L.size();++i) cout << L[i] << " "; delete p; vector<int> E; return 0; }
转载请注明原文地址: https://www.6miu.com/read-80701.html

最新回复(0)