排序算法的实现(归并,快排,堆排,希尔排序 O(N*log(N)))
Posted 小河沟大河沟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法的实现(归并,快排,堆排,希尔排序 O(N*log(N)))相关的知识,希望对你有一定的参考价值。
今天跟着左老师的视频,理解了四种复杂度为 O(N*log(N))的排序算法,以前也理解过过程,今天根据实际的代码,感觉基本的算法还是很简单的,只是自己写的时候可能一些边界条件,循环控制条件把握不好。
//对于一个int数组,请编写一个选择冒泡算法,对数组元素排序。 //给定一个int数组A及数组的大小n,请返回排序后的数组。 //测试样例: //[1, 2, 3, 5, 2, 3], 6 //[1, 2, 2, 3, 3, 5] #include <iostream> using namespace std; #include<string> void printResult(string str,int* A,int n) { cout << str << "的结果:\n"; for (int i = 0; i < n; i++) { cout << A[i] <<" "; } cout << endl; } void swap(int *a, int *b) { int temp=*a; *a = *b; *b = temp; } //冒泡排序 O(n^2) class BubbleSort { public: int* bubbleSort(int* A, int n) { // write code here for (int i = 0; i<n; i++) { for (int j = 0; j<n - i - 1; j++) { if (A[j]>A[j + 1]) { int temp = A[j]; A[j] = A[j + 1]; A[j + 1] = temp; } } } return A; } }; //请编写一个选择排序算法 O(n^2) class SelectionSort { public: int* selectionSort(int* A, int n) { // write code here int k = 0; for (int i = 0; i < n-1; i++) { k = i; for (int j = i; j < n; j++) { if (A[k]>A[j]) { k = j; } } if (k!=i) { int temp = A[i]; A[i] = A[k]; A[k] = temp; } } return A; } }; //请编写一个插入算法 O(n^2) class InsertionSort { public: int* insertionSort(int* A, int n) { for (int i = 1; i < n; i++) { int temp = A[i]; int j = i - 1; for (; j >= 0;j--) //j前面的已经排好序,从后面往前比较,当没有比当前值大的时候bereak; { if (A[j]>temp) { A[j + 1] = A[j]; } else { break; } } A[j + 1] = temp; } return A; } }; //归并排序 O(N*log(N)) class MergeSort { public: int* mergeSort(int* A, int n) { // write code here mergeSort(A, 0, n - 1); return A; } void mergeSort(int* A, int beg, int end) { if (beg < end) { int mid = beg + (end - beg) / 2; mergeSort(A, beg, mid); mergeSort(A, mid + 1, end); merge(A,beg,mid,end); } return; } void merge(int* A, int beg_, int mid_, int end_) { int *B = new int[end_ - beg_ + 1]; int index1 = beg_; int index2 = mid_ + 1; int i = 0; while (index1<=mid_&&index2<=end_) { if (A[index1]<=A[index2]) { B[i++] = A[index1++]; } else { B[i++] = A[index2++]; } } while (index1 <= mid_) { B[i++] = A[index1++]; } while (index2<=end_) { B[i++] = A[index2++]; } //memcpy(A,B,end_-beg_+1); for (int i = 0; i < end_ - beg_ + 1;i++) { A[beg_+i] = B[i]; //A[beg_++] 不能写,改变了输入参数 } delete[] B; } }; //快速排序 O(N*log(N)) #include <math.h> class QuickSort { public: int* quickSort(int* A, int n) { // write code here quickSort(A, 0, n - 1); return A; } void quickSort(int* A, int low, int high) { if (low <= high) { int part = partition(A, low, high); quickSort(A, low, part - 1); quickSort(A, part + 1, high); } return; } int partition(int* A, int low, int high) { int privotKey = A[low]; //基准元素 while (low < high) { //从表的两端交替地向中间扫描 while (low < high && A[high] >= privotKey) --high; //从high 所指位置向前搜索,至多到low+1 位置。将比基准元素小的交换到低端 swap(&A[low], &A[high]); while (low < high && A[low] <= privotKey) ++low; swap(&A[low], &A[high]); } return low; } }; class QuickSort2 { public: int* quickSort(int* A, int n) { // write code here quickSort(A, 0, n - 1); return A; } void quickSort(int* A, int low, int high) { if (low <= high) { int randn = low + rand() % (high - low + 1); //随机选择关键字的下标 swap(&A[randn], &A[high]); //void swap(int* A,int index1,int index2) //最好都操作下标 int part = partition(A, low, high); quickSort(A, low, part - 1); quickSort(A, part + 1, high); } return; } int partition(int* A, int low, int high) //O(N) { //int pivot = A[low];//很多随机选择放在这里面,而且是以值的形式确定,而非下标标记为关键字 int pivot = low-1; //关键字的位置 for (int i = low ; i <= high; i++) { if (A[i] <= A[high]) { swap(&A[i], &A[++pivot]); //感觉这样会把A数组前面的值覆盖?-->其实没有交换的效果就是把前面的交换到后面 } } return pivot; } }; //推排序 O(N*log(N)) class HeapSort { public: int* heapSort(int* A, int n) { // write code here buildHeap(A, n); //初始时构建堆 //从最后一个元素开始对序列进行调整 for (int i = n - 1; i >= 0;i--) { swap(&A[0], &A[i]); heapAdjust(A,0,i); } return A; } void buildHeap(int* A, int size_A) { for (int i = (size_A)/ 2-1; i >= 0; i--) { heapAdjust(A,i,size_A); } } void heapAdjust(int* A, int root, int size_A) //大顶堆 { int leftchild = 2 * root + 1; if (leftchild<size_A) //递归形式 { int rightchild = leftchild + 1; if (rightchild<size_A) { if (A[leftchild]<A[rightchild]) { leftchild = rightchild; } } //leftchild为左右子节点中较大的结点 if (A[root]<A[leftchild]) { int temp = A[root]; A[root] = A[leftchild]; //将较大结点值上移到根节点 A[leftchild] = temp; //完成交换,子节点变为以前的根节点 heapAdjust(A, leftchild, size_A); } } return; } }; class HeapSort2 { public: int* heapSort(int* A, int n) { // write code here buildHeap(A, n); //初始时构建堆 //从最后一个元素开始对序列进行调整 for (int i = n - 1; i >= 0; i--) { swap(&A[0], &A[i]); heapAdjust(A, 0, i); } return A; } void buildHeap(int* A, int size_A) { for (int i = (size_A - 1) / 2; i >= 0; i--) { heapAdjust(A, i, size_A); } } void heapAdjust(int* A, int root, int size_A) //调整为大顶堆 { int temp = A[root]; int leftchild = 2 * root + 1; while (leftchild < size_A) //非递归形式 { int rightchild = leftchild + 1; if (rightchild < size_A) { if (A[leftchild] < A[rightchild]) { leftchild = rightchild; } } //leftchild为左右子节点中较大的结点 if (A[root] < A[leftchild]) { A[root] = A[leftchild]; //将较大结点值上移到根节点 root = leftchild; //更新新的根节点 leftchild = 2 * root + 1; } else //当前结点大于左右子节点则不需要调整 { break; } A[root] = temp; //完成交换,子节点变为以前的根节点 } return; } }; //希尔排序 O(N*log(N)) ---不稳定 class ShellSort { public: int* shellSort(int* A, int n) { // write code here int dk = n / 2; while (dk>=1) { shellSort2(A,n,dk); dk /= 2; } return A; } void shellSort(int* A, int n, int dk) { for (int i = dk; i < n;i++) { int index = i; //当前访问的位置 while (index>=dk) { if (A[index-dk]>A[index]) { swap(&A[index-dk],&A[index]); //交换不算最优,找到插入位置才交换 index -= dk; } else { break; } } } } void shellSort2(int* A,int n,int dk) { for (int i = dk; i < n;i++) { if (A[i]<A[i-dk]) //找到插入位置 { int x = A[i];//复制哨兵 A[i] = A[i - dk]; int j = i - dk; //从该位置向前查找 while (x<A[j]&&j>=0) //防止j越界 { A[j] = A[j - dk]; j -= dk; //向前移动 } A[j + dk] = x;// 插入到正确位置 } } } }; #define N 13 int main() { //待排数据输入方式: /*int N = 0; cout << "排序数据个数:\n"; cin >> N; int* A = new int[N]; cout << "请输入待排序的数据:\n"; for (int i = 0; i < N; i++) { cin >> A[i]; }*/ //数据直接给定 int B[N] = { 1, 6, 3, 5, 2, 4 }; int C[13] = { 54, 35, 48, 36, 27, 12, 44, 44, 8, 14, 26, 17, 2 }; int* A = C; //从文件中读取,大量数据,计算时间复杂度 printResult("待排原始数据:", C, N); BubbleSort bubble; bubble.bubbleSort(A,N); printResult("bubbleSort", A, N); SelectionSort select; select.selectionSort(A, N); printResult("selectSort", A, N); InsertionSort insert; insert.insertionSort(A, N); printResult("InsetSort", A, N); MergeSort merge; merge.mergeSort(A, N); printResult("MergeSort", A, N); QuickSort qucik; qucik.quickSort(A, N); printResult("QucikSort",A,N); QuickSort2 qucik2; qucik2.quickSort(A, N); printResult("QucikSort2", A, N); HeapSort heap; heap.heapSort(A, N); printResult("heapSort", A, N); HeapSort2 heap2; heap2.heapSort(A, N); printResult("heapSort2", A, N); ShellSort shell; shell.shellSort(A,N); printResult("shellSort", A, N); return 0; }
以上是关于排序算法的实现(归并,快排,堆排,希尔排序 O(N*log(N)))的主要内容,如果未能解决你的问题,请参考以下文章
七大排序算法(插排,希尔,选择排序,堆排,冒泡,快排,归并)--图文详解
八大排序算法C语言过程图解+代码实现(插入,希尔,选择,堆排,冒泡,快排,归并,计数)