数据结构里的一些排序算法及其初级优化 v1.0

来源:互联网 发布:光晕系列 知乎 编辑:程序博客网 时间:2024/06/07 10:41

以下代码包含 冒泡排序、选择排序、插入排序、谢尔排序、堆排序、归并排序、快速排序

这伙是测试用数据类
waitForSort.h

#ifndef WAITFORSORT_H#define WAITFORSORT_H#include <iostream>#include "time.h"const int MAXSIZE = 1000;class waitForSort{public:int data[MAXSIZE];int length;waitForSort(const int, const int);void swap(const int, const int);void outPut();};#endif

waitForSort.cpp
#include "waitForSort.h"waitForSort::waitForSort(const int n, const int range) : length(n){srand(static_cast<int>(time(0)));for(int iter = 0; iter != n; ++iter)data[iter] = rand() % range;}void waitForSort::swap(const int a, const int b){int temp = data[a];data[a] = data[b];data[b] = temp;}void waitForSort::outPut(){for(int iter = 0; iter != length; ++iter){if(iter % 10 == 0)std::cout<<std::endl;std::cout<<data[iter]<<"  ";}}

ok,上算法...

Sorting.h

#include "waitForSort.h"#include <math.h>/**********************冒泡排序(改)**********************/void BubbleSort(waitForSort &L){const int NUM = L.length - 1;//空间换时间bool flag = true;for(int iter = 0; iter != NUM && flag; iter++){flag = false;for(int r = NUM; r != iter; r--){if(L.data[r] < L.data[r - 1]){L.swap(r - 1, r);flag = true;}}}}/**********************选择排序**********************/void SelectSort(waitForSort &L){const int NUM = L.length - 1;int min;for(int iter = 0; iter != NUM; iter++){min = iter;for(int r = iter + 1; r != L.length; r++)if(L.data[r] < L.data[min]){min = r;}if(min != iter)L.swap(min, iter);}}/**********************插入排序**********************/void InsertSort(waitForSort &L){int temp, iter, r;const int NUM = L.length - 1;for(iter = 0; iter != NUM; iter++){if(L.data[iter] > L.data[iter + 1]){temp = L.data[iter + 1];for(r = iter; L.data[r] > temp && r >= 0; r--)//此处要注意,防止越界L.data[r + 1] = L.data[r];L.data[r + 1] = temp;}}}/**********************谢尔排序**********************///谢尔排序可以看作选择排序的改进版,基本思想是通过元素的大//范围跃迁减少不必要的迭代次数,从而降低时间复杂度。void InsertShell(const int &gap, const int &NUM, waitForSort &L){int iter, r, temp;for(iter = gap; iter <= NUM; iter++){temp = L.data[iter];for(r = iter; r >= gap && L.data[r - gap] > temp; r -= gap)L.data[r] = L.data[r - gap];L.data[r] = temp;}}void ShellSort(waitForSort &L, int key){const int NUM = L.length - 1;int k = 0, p[20];int sedgewick[] = {//实践中总结出来的一个比较高效的增量集合               1073643521, 603906049, 268386305, 150958081, 67084289,              37730305, 16764929, 9427969, 4188161, 2354689,              1045505, 587521, 260609, 146305, 64769,              36289, 16001, 8929, 3905, 2161,              929, 505, 209, 109, 41,              19, 5, 1, 0};  switch(key){case 1://使用谢尔增量for(int gap = NUM / 2; gap > 0; gap /= 2)InsertShell(gap, NUM, L);break;case 0://使用Hibbard增量for(int iter = 0; iter != 20; iter++, k++){p[iter] = pow(static_cast<double>(2), iter + 1) - 1;if(p[iter] > NUM)break;}while(k != 0){InsertShell(p[--k], NUM, L);}break;case -1://使用经验增量while(sedgewick[k] > NUM)k++;k--;while(sedgewick[k] > 0){InsertShell(sedgewick[k++], NUM, L);}break;}}/**********************堆排序**********************///堆,本质上是拥有特殊性质的完全二叉树//makeHeap函数,将处于第i层的节点与其 已形成大顶堆//的子树调整为一个新的大顶堆!void makeHeap(waitForSort &L, int start, int end){//start, end均为第x个元素(A类),为(下标数 + 1)int temp;temp = L.data[start - 1];for(int iter = 2 * start; iter <= end; iter *= 2){//attention! iter为A类数据if(iter < end && L.data[iter - 1] < L.data[iter])//若left child < right child++iter;if(temp >= L.data[iter - 1])//可以看到,这里运用了选择排序的思想break;L.data[start - 1] = L.data[iter - 1];start = iter;}L.data[start - 1] = temp;}void HeapSort(waitForSort &L){int iter;//A类数据for(iter = L.length / 2; iter > 0; --iter)//iter指向的是每个拥有子树的节点,从后往前遍历makeHeap(L, iter, L.length);for(iter = L.length; iter > 1; --iter){L.swap(0, iter - 1);//将大顶堆的根节点(当前最大值)移至数据尾部makeHeap(L, 1, iter - 1);}}/**********************归并排序(递归版本)**********************/void Merge(int left[], int right[], int a, int b, int c){//将left[a to b] 与 left[b + 1 to c]归并到right[a to b], abc为数组下标int R_iter = a, A_stop = b;for(++b; a <= A_stop && b <= c; ++R_iter)right[R_iter] = left[a] < left[b] ? left[a++] : left[b++];//将下标a,b指向的值的较小者归入rigth[r_iter]for(; a <= A_stop; ++R_iter)right[R_iter] = left[a++];//将剩余值归并for(; b <= c; ++R_iter)right[R_iter] = left[b++];//同上}void MSort(int left[], int right[], int a, int b){//分割元素后归并  if(a == b){  right[a] = left[a];  return;  }  else{int TempSave[MAXSIZE];int mid = (a + b) / 2;MSort(left, TempSave, a, mid);MSort(left, TempSave, mid + 1, b);Merge(TempSave, right, a, mid, b);  }}void MergeSort_1(waitForSort &L){//这种编程方法有利于封装MSort(L.data, L.data, 0, L.length - 1);}/**********************归并排序(迭代版本)**********************///俗话说,能不用递归就不用递归,为了保证空间跟时间复杂度,下面//给出迭代版本//将重用上面定义的Merge方法void MergeStep(int left[], int right[], int width, int end){//注意,end为A类数据int i = 1;while(i <= end - 2 * width + 1){Merge(left, right, i - 1, i + width - 2, i + 2 * width - 2);//宽度为width的数据两两归并i += 2 * width;}if(i < end - width + 1)Merge(left, right, i - 1, i + width - 2, end - 1);elsefor(int iter = i - 1; iter < end; ++iter)//此处可用以防止出现width>end的情况出现right[iter] = left[iter];}void MergeSort_2(waitForSort &L){int *p = new int[L.length];//用同一片地址来存储中间数据~int k = 1;while(k < L.length){MergeStep(L.data, p, k, L.length);k *= 2;MergeStep(p, L.data, k, L.length);k *= 2;}}/**********************快速排序**********************///思路很简单,没啥好说的..int Location(waitForSort &L, int low, int high){int Key;Key = L.data[low];//简单的取首值while(low < high){while(low < high  && L.data[high] >= Key){--high;}L.swap(low, high);while(low < high && L.data[low] <= Key){++low;}L.swap(low, high);}return low;}void QuickSortRecursion(waitForSort &L, int low, int high){int pivot;//中轴if(low < high){pivot = Location(L, low, high);QuickSortRecursion(L, low, pivot - 1);QuickSortRecursion(L, pivot + 1, high);}}void QuickSort(waitForSort &L){QuickSortRecursion(L, 0, L.length - 1);}/**********************快排优化版**********************/int better_Location(waitForSort &L, int low, int high){int Key;//Key = L.data[low];//简单的去首值//////////////////////////////////优化1////////////////////////////////////////////////////////int mid = (high + low) / 2;if(L.data[low] > L.data[high])L.swap(low, high);if(L.data[mid] > L.data[high])L.swap(mid, high);if(L.data[low] < L.data[mid])L.swap(mid, low);//low所指向的数为三数间的中间数,此为三数取中法。可考虑增加抽样率提高准确性Key = L.data[low];/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////优化2////////////////////////////////////////////////////////while(low < high){while(low < high  && L.data[high] >= Key){--high;}//L.swap(low, high);L.data[low] = L.data[high];while(low < high && L.data[low] <= Key){++low;}//L.swap(low, high);L.data[high] = L.data[low];}L.data[low] = Key;////////////////////////////////////////////////////////////////////////////////////////////////return low;}///////////////////////////////////////优化3///////////////////////////////////////////////////////void better_QuickSortRecursion(waitForSort &L, int low, int high){int pivot;//中轴if((high - low) > 50){//超过50时用快排,否则直接插入排序while(low < high){pivot = better_Location(L, low, high);better_QuickSortRecursion(L, low, pivot - 1);low = pivot + 1;//优化尾递归}}elseInsertSort(L);}/////////////////////////////////////////////////////////////////////////////////////////////////////void better_QuickSort(waitForSort &L){better_QuickSortRecursion(L, 0, L.length - 1);}




原创粉丝点击