C++诸多排序算法

  • P1:初始化部分 [initial part]
    • 1.构造函数 [Constructed function]
    • 2.随机生成 [random create]
    • 3.通过字符串调用成员函数 [call method by string]
  • P2:排序部分 [sort part]
    • 1.选择排序 [select sort]
    • 2.插入排序 [insert part]
    • 3.快速排序 [quick sort]
    • 4.堆排序 [heap sort]
    • 5.标准库:sort [STL:sort]
    • 6.标准库:stable_sort [STL:stable_sort]
    • 7.冒泡排序 [bubble sort]
    • 8.鸡尾酒排序 [cocktail sort]
    • 9.地精排序 [gnome sort]
    • 10.希尔排序 [shell sort]
    • 11.双调排序【非递归】 [bitonic sort]
    • 12.双调排序【递归】 [recursive bitonic sort]
    • 13.猴子排序 [bogo sort]
    • 14.归并排序 [merge sort]
    • 15.LSD排序 [LSD sort]
    • 16.MSD排序 [MSD sort]
  • P3:相关链接 [relative link]
    • 1.参考链接 [reference link]
    • 2.参考文档 [reference doc]
    • 3.在线编译 [online editor]
    • 4.相关论坛 [relative forums]
    • 5.给我写信 [write e-mail]
    • 6.下载资源 [download code]

前言:个人觉得在这些函数里面注释足够详细,不需要太多的解释,适合有基础的人看,主要是用来回忆算法细节,快速捡起该算法。其实是应为我实在写不动了,最近既要找工作,又要写毕设,却是有点忙不过来。而且源码1000多行,写注释写到吐的我也真的是醉了,甚至想扔出一只只嘤嘤怪,然后开始一局嘤嘤怪忍者,emm~
.
它如同参考文档,在未来的开发中起着指导性作用,但是不可直接拿来使用;在实际应用中可能比这个要复杂的多,需要进行更多的优化与改进。
.
如果想要更加详细的掌握每一种排序算法,可以在点击最下端的相关链接,都是我参考过的,也可以自行百度,拿着别人的算法与本算法进行比对,带着这里的注释,去看懂别处的代码。
.
如果想要直接运行可以点击最下端的下载链接,上面有VS2019的工程文件,里面写的比较详细,整体观比较强,因目前还没有上传GitHub,CSDN现在不可以设置免费下载,所以见谅。
.
不过还是可以get到源文件的,可以✉给我写信✉,或者是将下面的函数自己整理到对应的文件中,自己运行一下也是可以的。
.
在下面的代码段中,对常见的部分莫过于数据的拷贝,memcpy函数的使用,why?

1.因为本文实现了一个类,类中有多个排序方法,但是却只有一组数据;
2.为了方便测试,只能每次排序的时候都拷贝一份,而后返回有序数组;
3.同样为了方便测试,所有排序最后都可以通过一个无参函数进行调用。

Note:一定要把上面的文字看完,否则容易产生误解。

P1:初始化部分 [initial part]

为方便使用排序算法,设置了一个可以根据外部数据进行初始化的构造函数。
为方便测试排序算法,设置了一颗可以自动生成待排数组的构造函数。

1.构造函数 [Constructed function]

/***************************************************
**名称:Cpp_Sorts
**参数:data:给定数组,num:数组长度
**返回:无
**功能:根据指定的数组和长度对类对象进行初始化
**性能:
**注意:一定要初始化map
****************************************************/
Cpp_Sorts::Cpp_Sorts(int const* data, const int num) {this->data = new int[num];this->num = num;memcpy(this->data, data, sizeof(int) * num);//将传入的数据,拷贝到this->data中ini_func();//记得初始化【字符串-函数名】map
}
/***************************************************
**名称:Cpp_Sorts
**参数:left:随机下限,right:随机上限,num:生成随机数的个数
**返回:无
**功能:根据上下限,生成num个随机数,并初始化map
**性能:
**注意:初始化map
****************************************************/
Cpp_Sorts::Cpp_Sorts(int const left, int const right, int const num) {random_arr(left, right, num);ini_func();//记得初始化【字符串-函数名】map
}

2.随机生成 [random create]

/***************************************************
**名称:random_arr
**参数:begin:随机下限,end:随机上限,num:随机数个数
**返回:无
**功能:根据上下限生成num个随机数,并且给该类成员赋值
**性能:
**注意:data要申请空间
****************************************************/
void Cpp_Sorts::random_arr(int begin, int end, int num) {this->num = num;data = new int[this->num];srand((unsigned int)time(NULL));//初始化种子for (int i = 0; i < this->num; i++) {data[i] = rand() % (end - begin + 1) + begin;//成成[begin,end]的随机数}
}

3.通过字符串调用成员函数 [call method by string]

/***************************************************
**名称:ini_fun
**参数:无
**返回:无
**功能:初始化【字符串-函数名】的map
**性能:
**注意:注意下面的书写格式,不能变
****************************************************/
void Cpp_Sorts::ini_func() {fun_map["select"] = &Cpp_Sorts::s_select;fun_map["insert"] = &Cpp_Sorts::s_insert;fun_map["quick"] = &Cpp_Sorts::s_quick;fun_map["heap"] = &Cpp_Sorts::s_heap;fun_map["std_sort"] = &Cpp_Sorts::s_sort;fun_map["std_stable_sort"] = &Cpp_Sorts::s_stable_sort;fun_map["bubble"] = &Cpp_Sorts::s_bubble;fun_map["cocktail"] = &Cpp_Sorts::s_cocktail;fun_map["shell"] = &Cpp_Sorts::s_shell;fun_map["botonic"] = &Cpp_Sorts::s_bitonic_rec;fun_map["merge"] = &Cpp_Sorts::s_merge;fun_map["LSD"] = &Cpp_Sorts::s_LSD;fun_map["MSD"] = &Cpp_Sorts::s_MSD;fun_map["gnome"] = &Cpp_Sorts::s_gnome;fun_map["bogo"] = &Cpp_Sorts::s_bogo;
}
/***************************************************
**名称:use_function
**参数:fun_name:函数名字
**返回:无
**功能:根据函数名字,调用类的成员函数,并计算函数运行的时间
**性能:
**注意:调用之前一定要初始化
****************************************************/
void Cpp_Sorts::use_function(string fun_name) {cout << "Using sort: " << fun_name << endl;auto start = steady_clock::now();//时钟开始int* arr = (this->*fun_map[fun_name])();auto end = steady_clock::now();//时钟结束print_arr(arr);//打印数组auto dur = duration_cast<microseconds>(end - start);//计算间隔cout << "Time consumption: " << dur.count() << "μs" << endl;
}

P2:排序部分 [sort part]

1.选择排序 [select sort]

描述:反复从序列中选出极值元素放置在序列一段[已经选择过的象征性剔除]

  1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
  3. 重复第二步,直到所有元素均排序完毕。
/***************************************************
**名称:s_select
**参数:无
**返回:排好顺序的数组的指针
**功能:统一接口,调用之后自动排序
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_select() {return s_select(this->data, this->num);
}
/***************************************************
**名称:s_select
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:拷贝一个data数组,并对数组元素进行排序
**性能:最好O(n^2),平均O(n^2),最坏O(n^2)
**注意:分两段,两重循环
****************************************************/
int* Cpp_Sorts::s_select(int const* data, const int num) {//拷贝副本int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//选择排序//选择一个最小的元素与第i个元素进行交换//小元素最后都放在前面,有序段越来越长//第一轮循环用于遍历所有元素//这个代码还是很好的懂的,你细品for (int min, i = 0; i < num - 1; i++) {min = i;//第二轮循环用来找最小元素的下标for (int j = i + 1; j < num; j++) {if (arr[min] > arr[j]) {min = j;}}//找到最小元素,进行交换if (min != i) {arr[min] ^= arr[i] ^= arr[min] ^= arr[i];}}return arr;
}

2.插入排序 [insert part]

描述:顺序选择序列中的元素插入到有序数据段中[象征性的分割原始序列]

  1. 将排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
  2. 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果有相等则插入到相等元素的后面。[规则可以自己定义])
/***************************************************
**名称:s_insert
**参数:无
**返回:有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_insert() {return s_insert(this->data, this->num);
}
/***************************************************
**名称:s_insert
**参数:data:原始数组,num:数组长度
**返回:有序数组的指针
**功能:拷贝原始数组,并对新数组排序返回
**性能:最好O(n),平均O(n^2),最坏O(n^2)
**注意:分两段,两重循环
****************************************************/
int* Cpp_Sorts::s_insert(int const* data, const int num) {//拷贝副本int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//插入排序//插入排序前段有序,后端无序//每次从后段里面取出一个,从后向前对前段元素进行比较,到合适位置进行插入//第一轮循环用于遍历尾部未知元素for (int i = 1; i < num; i++) {int temp = arr[i];int j = i - 1;//第二轮循环用于挪动前段有序元素,给待插入元素腾位置//如果有序段全都挪动了位置,说明这个元素最小//如果找到一个元素比当前元素小,就把当前元素紧随其后放置//意即,找到一个不比temp大的元素,将temp放在该元素的后面while ((j >= 0) && (arr[j] > temp)) {arr[j + 1] = arr[j];//有序段元素相逐渐后撤j--;}//如果有序段发生了变化if (j != i - 1) {arr[j + 1] = temp;}}return arr;
}

3.快速排序 [quick sort]

描述:置元素于选定的基准两侧,逐步递归

  1. 从数列中挑出一个元素,称为 “基准”(pivot);
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
/***************************************************
**名称:s_quick
**参数:无
**返回:指向有序数数组的指针
**功能:统一接口
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_quick() {return s_quick(this->data, this->num);
}
/***************************************************
**名称:s_quick
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:调用重载的s_quick函数
**性能:
**注意:high索引值
****************************************************/
int* Cpp_Sorts::s_quick(int const* data, const int num) {//拷贝副本//由于快排要改变当前数组,所以在递归前进行拷贝int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);return s_quick(arr, 0, num - 1);//确保高端元素的索引不超出范围
}
/***************************************************
**名称:s_quick
**参数:arr:待排序数组,low:左端,high:右端
**返回:返回有序数组的指针
**功能:对数组进行排序,并返回指向该数组的指针
**性能:最好:O(nlogn),平均O(nlogn),最坏:O(n^2)
**注意:下标别弄混
****************************************************/
int* Cpp_Sorts::s_quick(int* arr, int const low, int const high) {if (high <= low) return arr;//当汇聚到中间的时候退出int i = low, j = high + 1, key = arr[low];//默认第一个元素是key,下面是--j,所以这里写的是j=high+1while (true) {while (arr[++i] < key && (i != high));  //从左向右找比key大的值while (arr[--j] > key && (j != low));   //从右向左找比key小的值if (i >= j) break;arr[i] ^= arr[j] ^= arr[i] ^= arr[j];   //交换i,j对应的值,交换之后j位置的值是比low小的}if (low < j)//确保使用异或进行数值交换的是两个不一样的值arr[low] ^= arr[j] ^= arr[low] ^= arr[j];//中枢值与j对应值交换,去报中数值在中间s_quick(arr, low, j - 1);s_quick(arr, j + 1, high);
}

4.堆排序 [heap sort]

描述:建立二叉堆并反复摘取最大元

  1. 创建一个堆 H[0……n-1];
  2. 把堆首(最大值)和堆尾互换;
  3. 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
  4. 重复步骤 2,直到堆的尺寸为 1
/***************************************************
**名称:s_heap
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_heap() {return s_heap(this->data, this->num);
}
/***************************************************
**名称:s_heap
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:堆排序
**性能:最好=平均=最坏=O(nlogn)
**注意:
****************************************************/
int* Cpp_Sorts::s_heap(int const* data, int const num) {//拷贝副本int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//排序//神奇的是,调整的过程与建立大根堆的过程是一致的//建立大根堆for (int i = num / 2 - 1; i >= 0; i--) {//注意这里是从最后一个根节点开始的,可以自己代入试一试,确实是最后一个节点s_max_heapify(arr, i, num - 1);//实际上的建立大根堆过程,最后一个节点的计算公式准确无误}//每次浮上一个最小元素,沉下一个最大元素for (int i = num - 1; i > 0; i--) {arr[0] ^= arr[i] ^= arr[0] ^= arr[i];//交换首尾两个元素的位置s_max_heapify(arr, 0, i - 1);//末尾少去一个元素之后,再进行调整}return arr;
}
/***************************************************
**名称:s_max_heapify
**参数:arr:待排序数组,start:数组首位,end:数组末位
**返回:指向具有堆序性的数组的指针
**功能:见于函数内部
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_max_heapify(int* arr, int const start, int const end) {//两个功能://1、对于任意三个元素(one dad,two sons)进行大根堆调整//2、当大根堆建立完毕之后,让小元素下沉,大元素上升。//【由于大根堆已经建立完毕,所以能浮在上层的一定是大元素,而且不会有比他更大的,而小元素则会继续下沉,直到一个合适的位置】int dad = start;int son = dad * 2 + 1;while (son <= end) {if (son + 1 <= end && arr[son] < arr[son + 1])//从子节点中选择一个比较大的,并且标记下标son++;if (arr[dad] > arr[son])//如果父节点更大,就直接返回return arr;else {//否则就应该将父子节点交换,让大的在上面arr[dad] ^= arr[son] ^= arr[dad] ^= arr[son];dad = son;//然后更加深入让小元素沉到海底son = dad * 2 + 1;}}
}

5.标准库:sort [STL:sort]

描述:标准库函数,sort()排序不是稳定排序,sort是主要用到了快速排序(平均时间复杂度为O(nlogn)),还结合了插入排序(时间复杂度为O(n²))和堆排序(时间复杂度为O(nlogn))

/***************************************************
**名称:s_sort
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_sort() {return s_sort(this->data, this->num);
}
/***************************************************
**名称:s_sort
**参数:data:原始数组,num:元素个数
**返回:指向有序数组的指针
**功能:拷贝,排序,返回指针
**性能:平均O(nlogn)
**注意:这里使用的是标准库函数
****************************************************/
int* Cpp_Sorts::s_sort(int const* data, int const num) {//创建副本int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//排序/*int*beg=std::begin(arr);//begin()可以直接对于数组元素使用,但是不能动态数组使用int* end = end(arr);*///对数组使用迭代器的方式,尾部并不是最后一个元素,而是最后一个元素后的一个空元素std::sort(&arr[0], &arr[num]);return arr;
}

6.标准库:stable_sort [STL:stable_sort]

描述:标准库函数,保证最坏的排序效率。

/***************************************************
**名称:s_stable_sort
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_stable_sort() {return s_sort(this->data, this->num);
}
/***************************************************
**名称:s_stable_sort
**参数:data:原始数组,num:元素个数
**返回:指向有序数组的指针
**功能:拷贝,排序,返回指针
**性能:最坏:O(n(logn)^2),保证最坏情况
**注意:标准库函数,稳定排序
****************************************************/
int* Cpp_Sorts::s_stable_sort(int const* data, int const num) {//创建副本int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//排序/*int*beg=std::begin(arr);//begin()可以直接对于数组元素使用,但是不能动态数组使用int* end = end(arr);*///对数组使用迭代器的方式,尾部并不是最后一个元素,而是最后一个元素后的一个空元素std::stable_sort(&arr[0], &arr[num]);return arr;
}

7.冒泡排序 [bubble sort]

描述:两两比较选择大者依次排列在最后[设定判定标志]

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
/***************************************************
**名称:s_bubble
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_bubble() {return s_bubble(this->data, this->num);
}
/***************************************************
**名称:s_bubble
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:拷贝,排序,返回指针
**性能:最好:O(n)[改进之后],平均:O(n^2),最坏:O(n^2)
**注意:可以添加标记位,标记是否需要排序。[一般都是需要的]
**注意:数据少的时候性能还是不错的
****************************************************/
int* Cpp_Sorts::s_bubble(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//sort//冒泡排序需要两次循环//第一重循环用来缩减前段待排序列//第二循环用来将大元素交换到最后//version_1,习惯使用版本一,方便书写。for (int i = 0; i < num - 1; i++)for (int j = 0; j < num - 1 - i; j++)if (arr[j] > arr[j + 1])arr[j] ^= arr[j + 1] ^= arr[j] ^= arr[j + 1];//version_2/*bool exchange;//设置标记位,是否发生了交换for (int i = 0; i < num - 1; i++) {exchange = false;for (int j = 0; j < num - 1 - i; j++) {if (arr[j] > arr[j + 1]) {arr[j] ^= arr[j + 1] ^= arr[j] ^= arr[j + 1];exchange = true;}}if (!exchange) break;//如果没有发生交换,就直接退出}*/return arr;
}

8.鸡尾酒排序 [cocktail sort]

描述:相邻元素成对比较,确定大小两值置于两端

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
/***************************************************
**名称:s_cocktail
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_cocktail() {return s_cocktail(this->data, this->num);
}
/***************************************************
**名称:s_cocktail
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:拷贝,排序,返回
**性能:最好:O(n),平均:O(n^2),最坏:O(n^2)
**注意:
****************************************************/
int* Cpp_Sorts::s_cocktail(int const* data, int const num) {//实质上是一个双向的冒泡排序int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//sort//1.先从左到右,两两进行对比,将大的元素浮动到最右侧,记录下右边界//2.再从右到左,两两进行对比,将小的元素浮动到最左侧,记录下左边界//3.直到某次不发生交换,就返回int left = 0, bounder = 0, right = num - 1;//标记边界的bound是必须的,不能直接使用right or leftbool swepped = true;//如果没有发生过交换,可以直接返回while (swepped) {swepped = false;for (int i = left; i < right; i++) {if (arr[i] > arr[i + 1]) {arr[i] ^= arr[i + 1] ^= arr[i] ^= arr[i + 1];swepped = true;bounder = i;//每次标记右边界,bounder现在刚好是小元素的位置}}right = bounder;//更新右边界,这里都是刚好的,不用进行加减等麻烦的操作for (int i = right; i > left; i--) {if (arr[i] < arr[i - 1]) {arr[i] ^= arr[i - 1] ^= arr[i] ^= arr[i - 1];swepped = true;bounder = i;//每次标记左边界,bounder现在刚好是大元素的位置}}left = bounder;//更新左边界}return arr;
}

9.地精排序 [gnome sort]

描述:设置标识,前进冒泡一次后折返,循环到达元素末尾时终止

  1. 只有一层循环,默认情况下前进冒泡
  2. 一旦遇到冒泡的情况发生就往回冒,直到把这个数字放好为止
/***************************************************
**名称:s_gnome
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_gnome() {return s_gnome(this->data, this->num);
}
/***************************************************
**名称:s_gnome
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:拷贝,排序,返回指针
**性能:最好:O(n),平均:O(n^2),最坏O(n^2)
**注意:
****************************************************/
int* Cpp_Sorts::s_gnome(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//gnome//1.顺序向后,两两对比,直到遇见更小的元素//2.从该元素开始往回冒泡,直到将其放到正确的位置//3.再从该位置向后走,如遇类似情形就重复1/2操作int i = 0;//没有必要在语法上进行缩减,而应还从算法上进行精化while (i < num) {if (i == 0 || arr[i - 1] <= arr[i]) {i++;//用于退出的量,只要是向右走,就要进行加·1}else {arr[i - 1] ^= arr[i] ^= arr[i - 1] ^= arr[i];i--;//向左走的就要减1}}return arr;
}

10.希尔排序 [shell sort]

描述:视作二维矩阵逐步压缩行高

  1. 选择一个增量序列 t1,t2,……,tk,前者大于后者,tk = 1;[可以反过来定义,算法需要修改]
  2. 按增量序列个数 k,对序列进行 k 趟排序;
  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。
  4. 仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
/***************************************************
**名称:s_shell
**参数:无
**返回:指向有序元素的指针
**功能:随机使用两种不同的希尔排序
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_shell() {srand(time(0));if (rand() % 2 == 0)return s_shell_1(this->data, this->num);elsereturn s_shell(this->data, this->num);
}
/***************************************************
**名称:s_shell
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:进行希尔排序
**性能:平均:O(n^(7/6)),最坏:O(n^(4/3)),[斐波那契数列]:O(n^(3/2))
**注意:有一部分人会自己规定gap序列Wie斐波那契数列,似乎是效率比较好
****************************************************/
int* Cpp_Sorts::s_shell(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//shell_sort//每一次gap都变为原来的1/2//loop-1:控制gap变小for (int gap = num / 2; gap > 0; gap /= 2) {//loop-2:控制插入排序的第一轮循环for (int i = gap; i < num; i++) {int j = i;//控制组//也算是插入排序,基于交换的//也有点像是冒泡排序,不过这个是向前的//可以理解为向前冒泡,或者是不完整的插入排序//loop-3:控制插入排序while (j - gap >= 0 && arr[j] < arr[j - gap]) {arr[j] ^= arr[j - gap] ^= arr[j] ^= arr[j - gap];j -= gap;}}}return arr;
}
/***************************************************
**名称:s_shell
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:进行希尔排序
**性能:平均:O(n^(7/6)),最坏:O(n^(4/3)),[斐波那契数列]:O(n^(3/2))
**注意:有一部分人会自己规定gap序列Wie斐波那契数列,似乎是效率比较好
****************************************************/
int* Cpp_Sorts::s_shell_1(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);//shell sort: version-1//大致流程与上面都是一样的int gap = 1;while (gap < num / 3)gap = gap * 3 + 1;while (gap >= 1) {//上一种方法这里是for循环,用的是while循环,gap>0等效于gap>=1for (int i = gap; i < num; i++) {//上面用的是while循环进行的插入排序//这里使用的是for循环进行插入排序//多一种写法,看着比较牛逼,其实是一个道理for (int j = i; j >= gap && arr[j] < arr[j - gap]; j -= gap) {arr[j] ^= arr[j - gap] ^= arr[j] ^= arr[j - gap];}}gap /= 3;}return arr;
}

11.双调排序【非递归】 [bitonic sort]

描述:[可以并行,效率会大大的提高。只能处理2^n个数的数据]

/***************************************************
**名称:s_bitonic
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_bitonic() {return s_bitonic(this->data, this->num);
}
/***************************************************
**名称:s_bitonic
**参数:data:原始数组,num:数组长度
**返回:指向有序数组的指针
**功能:进行非递归的双调排序
**性能:平均:O(n(logn)^2)[串行]
**注意:双调排序可以串行处理,在多机器的情况下效率是很高的
****************************************************/
int* Cpp_Sorts::s_bitonic(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);bool up = true;//将普通的无序序列转化为双调序列for (int step = 2; step < num; step *= 2) {for (int i = 0; i < num; i += 2 * step) {//事实上这两处的顺序并不重要,只要满足双调序列的定义即可//双调数列的构建过程://2(1),4(2,1),8(4,2,1),16(8,4,2,1)//括号里面每次都是需要逐渐深入的//代码需要时常观摩s_bitonic(arr + i, step, up);//前半段递增s_bitonic(arr + step + i, step, !up);//后半段递减}}return s_bitonic(arr, num, up);//对双调序列进行排序,而后返回
}
/***************************************************
**名称:s_bitonic
**参数:arr:数组,num:元素个数,up:是否递增
**返回:满足双调序列定义的数组,或有序数组
**功能:1.构建双调序列 2.对于双调序列进行排序
**性能:
**注意:双调序列概念
****************************************************/
int* Cpp_Sorts::s_bitonic(int* arr, int const num, bool up) {//bitonic_sort//默认升序排列//可以对照参考链接仔细理解这里的//构建双调序列的时候,这里的num是逐渐扩倍的for (int step = num / 2; step > 0; step /= 2) {//步长缩减for (int i = 0; i < num; i += 2 * step) {//第i组元素for (int j = 0; j < step; j++) {//第i组元素与第i+1组元素的比较if (up) {//是否是增序if (arr[i + j] > arr[i + j + step])//前者大,则与后者换位arr[i + j] ^= arr[i + step + j] ^= arr[i + j] ^= arr[i + step + j];}else {//如果是降序if (arr[i + j] < arr[i + j + step])//前者小,则与后者换位arr[i + j] ^= arr[i + step + j] ^= arr[i + j] ^= arr[i + step + j];}}}}return arr;
}

12.双调排序【递归】 [recursive bitonic sort]

/***************************************************
**名称:s_bitonic_rec
**参数:无
**返回:指向有序数组的指针
**功能:统一接口
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_bitonic_rec() {return s_bitonic_rec(this->data, this->num);
}
/***************************************************
**名称:s_bitonic_rec
**参数:data:原始数组,num:元素个数
**返回:指向有序数组的指针
**功能:次级接口
**性能:
**注意:先进行数据拷贝
****************************************************/
int* Cpp_Sorts::s_bitonic_rec(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);bool up = true;//升序return s_bitonic_rec(arr, num, up);//调用双调排序
}
/***************************************************
**名称:s_bitonic_get_len
**参数:len:长度
**返回:参与双调排序的数据长度
**功能:找一个2的次幂,让它刚好比len小
**性能:
**注意:任何数字都可以拆成多2的幂级表达式的和(etc:15=2^3+2^2+2^1+2^0)
****************************************************/
int Cpp_Sorts::s_bitonic_get_len(int const len) {int k = 1;while (k < len) k = k << 1;//满足条件,扩大两倍return k >> 1;//上面循环最后一次运行,多扩大了一次,这里应该除下来
}
/***************************************************
**名称:s_bitonic_rec
**参数:arr:数组,len:元素个数,up:是否增序
**返回:指向有序数组的指针
**功能:递归双调排序
**性能:平均:O(n(logn)^2)[串行]
**注意:前半段降序,后半段升序
****************************************************/
int* Cpp_Sorts::s_bitonic_rec(int* arr, int const len, bool up) {if (len > 1) {int m = len / 2;//以下的强制顺序与递归的流程是有关系的//将整个流程走一遍,如果最后要求的是增序,在递归情况下为满足双调序列的定义,必须先降后增//如果最后要求的是降序排列,这里同样也需要先降后增//改变了顺序,程序就会输出错误的结果//之前非递归版本的不要求这样做,原因未知s_bitonic_rec(arr, m, !up);//前半段降序,递归要求一定要这么做,why?s_bitonic_rec(arr + m, len - m, up);//后半段升序//回收并不是所有的递归都结束之后才运行的//从最后一次不符合条件的递归开始,这个归并机制就已经开始起作用了//最深层的递归,逐渐向上调用这个归并机制s_bitonic_rec_merge(arr, len, up);//归并机制}return arr;
}
/***************************************************
**名称:s_bitonic_rec_merge
**参数:arr:数组,len:元素个数,up:是否增序
**返回:无
**功能:对于任意双调序列进行归并
**性能:
**注意:
****************************************************/
void Cpp_Sorts::s_bitonic_rec_merge(int* arr, int const len, bool up) {//任意双调排序的归并//此函数即能用来生成双调函数,也能用来归并,非常的经典if (len > 1) {int m = s_bitonic_get_len(len);//前半段的长度for (int i = 0; i < len - m; i++) {//源码中写的额是++i,其实并不影响,for循环中第一次使用的是初始化的0if (arr[i] > arr[i + m] == up)//如果是升序,会对交换两者,如果是降序,后者大,也需要对两者进行交换arr[i] ^= arr[i + m] ^= arr[i] ^= arr[i + m];//上面的判断条件很将就}s_bitonic_rec_merge(arr, m, up);//对于前半段递增归并,或者是递减,与下面的保持一致s_bitonic_rec_merge(arr + m, len - m, up);//对于后半段也递增,或者是递减}
}

13.猴子排序 [bogo sort]

描述:随缘吧!

/***************************************************
**名称:s_bogo
**参数:无
**返回:指向有序元素的指针
**功能:统一入口
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_bogo() {return s_bogo(this->data, this->num);
}
/***************************************************
**名称:s_get_dif_m_shu
**参数:index:递增数组,num:元素个数
**返回:指向打乱顺序的数组的指针
**功能:打乱递增数组的元素顺序
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_get_dif_m_shu(int* index, int const num) {std::random_device rd;std::mt19937 g(rd());shuffle(&index[0], &index[num], g);return index;
}
/***************************************************
**名称:s_bogo_is_order
**参数:arr:数组,index:下标数组,num:元素个数
**返回:是否有序bool类型值
**功能:根据index数组,判断arr数组中的元素是否有序
**性能:
**注意:
****************************************************/
bool Cpp_Sorts::s_bogo_is_order(int const* arr, int const* index, int const num) {//比如,arr[3,5,1,2],index[2,3,0,1]//将index中的元素作为arr的索引,可以有arr[2]<arr[3]<arr[0]<arr[1]//此时,根据index数组判断arr数组的元素是有序的for (int i = 1; i < num; i++) {if (arr[index[i]] < arr[index[i - 1]])return false;}return true;
}
/***************************************************
**名称:s_bogo——print
**参数:arr:数组,num:元素个数
**返回:无
**功能:打印
**性能:
**注意:就是想简单的输出一下,调试的时候使用的
****************************************************/
void Cpp_Sorts::s_bogo_print(int const* arr, int num) {for (int i = 0; i < num; i++)cout << arr[i] << ' ';cout << endl;
}
/***************************************************
**名称:s_bogo
**参数:data:数组,num:元素个数
**返回:指向有序数组的指针
**功能:模拟猴子按键的过程,每次不同的键位,看这些键位是否有序
**性能:极差
**注意:元素个数>10的时候不建议使用
****************************************************/
int* Cpp_Sorts::s_bogo(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);int* index = new int[num];//不知道这一部分空间应该在哪里删除掉iota(&index[0], &index[num], 0);//对数组进行递增的初始化,从0开始,每次+1index = s_get_dif_m_shu(index, num);//打乱下标数组中的元素while (!s_bogo_is_order(arr, index, num)) {//判断是否有序index = s_get_dif_m_shu(index, num);//若无序,就继续打乱//s_bogo_print(index, num);//打印猴子按键的过程}arr = s_bogo(data, index, num);return arr;
}
/***************************************************
**名称:s_bogo
**参数:arr:数组,index:下标数组,num:元素个数
**返回:指向有序数组的指针
**功能:根据index中的下标依次取arr中的元素,并回放index数组中
**性能:
**注意:这里取巧,让index数组充当了有序数组容器,并将其返回
****************************************************/
int* Cpp_Sorts::s_bogo(int const* arr, int* index, int const num) {for (int i = 0; i < num; i++) {index[i] = arr[index[i]];}return index;
}

14.归并排序 [merge sort]

这里需要一个非递归的版本,下次写好了之后添加上。

描述:2048[递归和迭代两个版本]

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
  4. 重复步骤 3 直到某一指针达到序列尾;
  5. 将另一序列剩下的所有元素直接复制到合并序列尾。
/***************************************************
**名称:s_merge_m
**参数:arr:数组,left:左下标,right:右下标,mid:中间下标
**返回:无
**功能:对于[left,right]之间的元素分两部分进行归并
**性能:
**注意:
****************************************************/
void Cpp_Sorts::s_merge_m(int* arr, int const left, int const right, int const mid) {int* temp = new int[right - left + 1];int i = 0, p1 = left, p2 = mid + 1;//取小的先放while (p1 <= mid && p2 <= right) {temp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];}//第一部分没放完的放置在后面while (p1 <= mid) {temp[i++] = arr[p1++];}//第二部分没放完的继续向后放while (p2 <= right) {temp[i++] = arr[p2++];}//将归并好的部分,拷贝给原来的数组memcpy(arr + left, temp, sizeof(int) * (right - left + 1));delete[] temp;//清除申请的内存
}
/***************************************************
**名称:s_merge_rec
**参数:arr:数组,left:左下标,right:右下标
**返回:无
**功能:递归进行归并排序
**性能:最好:O(nlogn),平均:O(nlogn),最坏:O(nlogn)
**注意:递归的两部分不要重复
****************************************************/
void Cpp_Sorts::s_merge_rec(int* arr, int const left, int const right) {if (left == right) return;int mid = (left + right) / 2;//思想是很简单的,但实际上这是一个递归的过程s_merge_rec(arr, left, mid);//对于左边递归s_merge_rec(arr, mid + 1, right);//对于右边进行递归,一定要+1确保不会重复s_merge_m(arr, left, right, mid);//如果两边都好了,就开始进行合并
}
/***************************************************
**名称:s_merge
**参数:data:原始数据,num:元素个数
**返回:指向有序数组的指针
**功能:调用归并排序
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_merge(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);s_merge_rec(arr, 0, num - 1);return arr;
}
/***************************************************
**名称:s_merge
**参数:无
**返回:指向有序数组的指针
**功能:统一入口
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_merge() {return s_merge(this->data, this->num);
}

15.LSD排序 [LSD sort]

描述:最低位优先批次进行排序,最后读取序列

  1. 首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:
  2. 接着再进行一次分配,这次是根据十位数来分配:
  3. 接下来将这些桶子中的数值重新串接起来,成为以下的数列:
  4. [位数变多则多进行几步]
/***************************************************
**名称:s_LSD
**参数:无
**返回:指向有序数组的指针
**功能:
**性能:
**注意:
****************************************************/
int* Cpp_Sorts::s_LSD() {return s_LSD(this->data, this->num);
}
/***************************************************
**名称:s_LSD
**参数:data:数组,num:元素个数
**返回:指向有序数组的指针
**功能:使用LSD对数组进行排序
**性能:最好:O(d(n+rd)),平均:O(d(n+r)),最坏:O(d(n+r))
**注意:
****************************************************/
int* Cpp_Sorts::s_LSD(int const* data, int const num) {int* arr = new int[num];memcpy(arr, data, sizeof(int) * num);int digit = s_LSD_get_d(arr, num);  //获取最高位的位数queue<int>* p_queue[10];            //指向队列的数组,指针数组,有10个queue<int>的指针,相当于算法中的十个桶for (int i = 0; i < 10; i++) {      //同时需要进行初始化p_queue[i] = new queue<int>;}int* temp = new int[num];           //出桶的时候临时存储数据for (int d = 1; d <= digit; d++) {  //每一位都要进行比较//入桶for (int i = 0; i < num; i++) { //进行一趟个位的排序,根据第n位进行入桶p_queue[arr[i] / (int)pow(10, d - 1) % 10]->push(arr[i]);}//出桶for (int i = 0, count = 0; i < 10; i++) {while (!p_queue[i]->empty()){temp[count++] = p_queue[i]->front();    //获取第一个元素p_queue[i]->pop();                      //第一个元素出队列}}//交换两个指针int* temp_2;temp_2 = arr;arr = temp;//保证每一次的arr都是经过排列的temp = temp_2;}delete[] temp;//清空临时指针指向的空间return arr;
}
/***************************************************
**名称:s_LSD_get_d
**参数:arr:数组,num:元素个数
**返回:数组中最大元素的位数
**功能:求数组中最大元素的位数
**性能:
**注意:同下面的s_MSD_get_d
****************************************************/
int Cpp_Sorts::s_LSD_get_d(int const* arr, int const num) {int max = arr[0];int digit = 1;for (int i = 1; i < num; i++) {if (arr[i] > max)max = arr[i];}while (max /= 10) {++digit;}return digit;
}

16.MSD排序 [MSD sort]

描述:高位分桶,桶内递归

  1. 先根据最高位关键码K1排序,得到若干对象组,对象组中每个对象都有相同关键码K1。
  2. 再分别对每组中对象根据关键码K2进行排序,按K2值的不同,再分成若干个更小的子组,每个子组中的对象具有相同的K1和K2值。
  3. 依此重复,直到对关键码Kd完成排序为止。
  4. 最后,把所有子组中的对象依次连接起来,就得到一个有序的对象序列。
/***************************************************
**名称:s_MSD
**参数:无
**返回:指向有序数组的指针
**功能:随机使用一种s_MSD算法
**性能:
**注意:不同的初始化方式
****************************************************/
int* Cpp_Sorts::s_MSD() {//随机使用一下两种中的一种//数据拷贝,有序s_MSD算法使用递归,会对数据自身进行调整,因此需要在这里进行数据拷贝int* arr = new int[this->num];memcpy(arr, this->data, sizeof(int) * this->num);int digit = s_LSD_get_d(arr, this->num);//获取最大数字的位数srand(time(0));int x = rand() % 2;x = 10;if (x == 0) {int* arr_back = new int[this->num];int count = 0;s_MSD(arr, this->num, digit, arr_back, count);return arr_back;}else {vector<int> A(arr, arr + num);//初始化一个向量s_MSD(A, digit);for (int i = 0; i < num; i++) {//排序结束之后将向量中的元素放入数组之中并且返回arr[i] = A[i];}return arr;}
}
/***************************************************
**名称:s_MSD
**参数:arr:数组,num:数组元素个数,digit:位数,arr_back:用于回收的数组,count:用于记录回收了几个元素
**返回:无
**功能:对arr进行递归的MSD算法,将回收的元素放入arr_back数组之中并返回
**性能:最好:O(d(n+rd)),平均:O(d(n+r))[r为基数,d为位数][n是放一趟的次数,r为收集一趟的次数],最坏:O(d(n+r))
**备注:关于性能的描述并不是特别懂
**注意:count一定要传引用,内存的清理
****************************************************/
void Cpp_Sorts::s_MSD(int* arr, int const num, int const digit, int* arr_back, int& count) {//最终的元素应该如何收集//这里的递归不太会使用//自己写的版本,不能使用arr自身进行数据的回收//要么使用vector<vector<int>>,要么使用二维数组,都可以正确使用arr自身进行数据的回收queue<int>* p_queue[10];            //十个桶for (int i = 0; i < 10; i++)        //对这十个桶进行初始化p_queue[i] = new queue<int>;for (int i = 0; i < num; i++)       //按照最高位入桶p_queue[arr[i] / (int)pow(10, digit - 1) % 10]->push(arr[i]);for (int i = 0; i < 10; i++) {      //对于十个桶进行遍历int size = p_queue[i]->size();if (size == 1) {                //如果size等于1说明这个桶里面只有一个元素,直接放入arr_back中即可arr_back[count++] = p_queue[i]->front();//回收}else if (size > 1) {int* arr_b = new int[size]; //新的待排序的数组,将现在这个桶里的元素放入其中for (int j = 0; j < size; j++) {arr_b[j] = p_queue[i]->front();p_queue[i]->pop();}s_MSD(arr_b, size, digit - 1, arr_back, count);//对于元素个数大于1的桶进行递归delete[] arr_b;             //清空之前arr_b申请的空间,清理内存}}
}
/***************************************************
**名称:s_MSD
**参数:vec:待排序向量,digit:最大元素的位数
**返回:无
**功能:对vec向量递归排序
**性能:最好:O(d(n+rd)),平均:O(d(n+r))[r为基数,d为位数][n是放一趟的次数,r为收集一趟的次数],最坏:O(d(n+r))
**注意:推荐这种算法,比较精妙
****************************************************/
void Cpp_Sorts::s_MSD(vector<int>& vec, int digit) {int len = vec.size();vector<vector<int>> p_vector(10);//声明10个桶,并进行初始化if (digit >= 1 && len > 1) {//如果位数不为0,而且桶中的元素个数大于1个for (int i = 0; i < len; i++)//对于桶中的元素进行分配p_vector[vec[i] / (int)pow(10, digit - 1) % 10].push_back(vec[i]);for (int i = 0, j = 0; i < 10; i++) {//递归进行排序s_MSD(p_vector[i], digit - 1);//上面判断过桶中元素个数是否>1,这里如果不满足,就会跳出该轮递归,进行下面的语句//加入之前有一个桶中的元素是(23,24,21),经过分配之后会变成{(21),(23),(24)}//然后对这三个元素调用s_MSD,都会被阻断,然后进入下面的回收机制中//vec是原来有三个元素的桶,经过分配之后它已经为空,p_vector[i]每一个桶//21,23,24会依次进入原来的vec桶中,它大小未变,但vec中的元素已经有序//当前vec所处的桶序列回收结束之后,又会进入上一级递归while (!p_vector[i].empty()) {//单次回收的时候都是对的vec[j++] = p_vector[i].front();p_vector[i].erase(p_vector[i].begin());//回收一个元素,释放一个元素}}}
}
/***************************************************
**名称:s_MSD_get_d
**参数:arr:数组,num:元素个数
**返回:数组中最大元素的位数
**功能:求数组中最大元素的位数
**性能:
**注意:
****************************************************/
int Cpp_Sorts::s_MSD_get_d(int const* arr, int const num) {int max = arr[0];int digit = 1;for (int i = 1; i < num; i++) {//找出最大元素if (arr[i] > max)max = arr[i];}while (max /= 10) {//除10不为零,说明有了有了一位++digit;//鉴于while循环的先判断性质,满足条件就直接先加上}return digit;
}

P3:相关链接 [relative link]

1.参考链接 [reference link]

1.C++ 随机生成区间范围内的随机数
2.标准库头文件 <algorithm>
3.标准库头文件 <numeric>
4.C++11标准库chrono库使用
5.基于C++11 chrono库的计时器
6.How to call a function by its name (std::string) in C++?
7.c++ 成员函数指针
8.error C3867:非标准语法;请使用“&”来创建指向成员的指针
9.error C3867:非标准语法;请使用“&”来创建指向成员的指针
10.c++基础之vector、数组初始化
11.【排序算法】基数排序:LSD 与 MSD
12.基数排序(LSD+MSD)详解
13.const 和 非const函数重载
14.C++ 求幂的运算符是什么?
15.c++中的运算符优先级
16.怎样快速提取一个数字中的每一位数
17.c++指针可以指向栈吗?
18.指针数组和数组指针的区别
19.C++ 标准库中的堆(heap)
20.分治法之归并排序三种实现方法(递归、非递归和自然合并排序)
21.基数排序(LSD)
22.十大经典排序算法(动图演示)
23.[图解] 归并排序
24.C++ iota()函数
25.std::shuffle-c++
26.C++ 11中的随机排列函数shuffle
27.网易有道编程题:洗牌算法(C++)
28.猴子排序法的实际意义?
29.排序算法——猴子排序(Bogosort)【代码实现】
30.Java排序 - 不实用的几个排序算法 – 睡眠排序、猴子排序、面条排序、珠排序
31.C++洗牌算法
32.栈的应用:栈混洗
33.栈混洗的概念
34.VS中展开和折叠代码,还有其他快捷操作
35.三十分钟理解:双调排序Bitonic Sort,适合并行计算的排序算法
36.【并行计算】Bitonic Sort(双调排序)基础
37.双调排序
38.五分钟学会一个高难度算法:希尔排序
39.指针常量和常量指针

2.参考文档 [reference doc]

1.cppreference.com
2.c++ reference oschina
3.cplusplus.com
4.c++ 中文手册 51yip
5.游戏蛮牛C++手册
6.C++ 教程 runoob
7.C++ References
8.C++ Tutorial w3schools
9.C++ Tutorial geeksforgeeks

3.在线编译 [online editor]

推荐使用前十个,最后一个,多数都不用上外网,前两个是菜鸟教程上的,【4】很简洁,【6】没有用过,似乎能建立工程,界面简单而且没有广告。

1.runoob.com
2.w3cschool.cn
3.godbolt.org
4.cpp.sh
5.ideone.com
6.winfengtech.com
7.c++ 代码测试
8.tool.lu/coderunner
9.wandbox.org
10.onlinegdb.com
11.jdoodle.com
12.tutorialspoint.com
13.codechef.com
14.codiva.io
15.geeksforgeeks
16.coliru
其他:
1.程序员专用十大在线编译器(IDE)整理
2.List of Online C++ Compilers

4.相关论坛 [relative forums]

1.https://isocpp.org/
2.CSDN C++论坛
3.stack overflow
4.综合型编程论坛
5.吾爱破解 - 编程语言区

5.给我写信 [write e-mail]

邮箱:2720878872@qq.com
写信地址:✉✉✉✉

6.下载资源 [download code]

下载:Cpp_Sort.zip

01-0003 C++诸多排序算法,前来报到~相关推荐

  1. 左神算法笔记01——排序算法

    十大排序算法 选择排序 遍历n次,每次找出i到n-1最小的值,和i位置的值做交换 时间复杂度为o(n²) public static void swap(int[] arr,int i,int j){ ...

  2. 排序算法(01)— 三种简单排序(冒泡、插入、选择)

    一.概述 排序是数据处理中十分常见且核心的操作,虽说实际项目开发中很小几率会需要我们手动实现,毕竟每种语言的类库中都有n多种关于排序算法的实现.但是了解这些精妙的思想对我们还是大有裨益的. 1.1 排 ...

  3. 十大经典排序算法Python版实现(附动图演示)

    来源:大数据DT 本文约5200字,建议阅读10分钟 排序算法是<数据结构与算法>中最基本的算法之一.本文介绍10种常见的内部排序算法,及如何用Python实现. 排序算法可以分为内部排序 ...

  4. access两字段同时升序排序_7 天时间,我整理并实现了这 9 种常见的排序算法

    排序算法 回顾 我们前面已经介绍了 3 种最常见的排序算法: java 实现冒泡排序讲解 QuickSort 快速排序到底快在哪里? SelectionSort 选择排序算法详解(java 实现) 然 ...

  5. 一文读懂Python版的十大经典排序算法(附动图演示)

    来源:大数据DT 本文约5200字,建议阅读10分钟 排序算法是<数据结构与算法>中最基本的算法之一.本文介绍10种常见的内部排序算法,及如何用Python实现. 排序算法可以分为内部排序 ...

  6. 【每日算法】C语言8大经典排序算法(2)

    接上文--->[每日算法]C语言8大经典排序算法(1) 二.插入类排序 插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中 ...

  7. Java数据结构与算法:排序算法

    1. 冒泡排序 冒泡排序(Bubble Sort),又被称为气泡排序或泡沫排序. 它是一种较简单的排序算法.它会遍历若干次要排序的数列,每次遍历时,它都会从前往后依次的比较相邻两个数的大小:如果前者比 ...

  8. 【zz】如何去理解 拓扑排序算法

    from http://www.cnblogs.com/shanyou/archive/2006/11/16/562861.html 查看Castle的代码,在Castle.Core中内部的数据结构采 ...

  9. Java排序算法总结

    稳定排序: * 泡沫排序(bubble sort) - O(n²) * 插入排序 (insertion sort)- O(n²) * 桶排序 (bucket sort)- O(n); 需要 O(k)  ...

最新文章

  1. 机器学习成为未来趋势 北美未来将保持最大市场规模
  2. bash shell实现二进制与十进制数的互转
  3. NIO网络编程实战之简单多人聊天室
  4. linux命令格式,常用10个LINUX命令说明
  5. source insight 支持lua /ruby
  6. 关于抢红包的_关于抢红包的话题800字作文
  7. 处理机流水线------经典五段流水线
  8. com.jhlabs:imaging:jar:01012005 所在仓库+captcha验证码maven依赖
  9. 模仿电影中黑客电脑界面,CMD装逼代码
  10. Python:摄氏温度转华氏温度
  11. 自己制作一个小程序需要多少钱
  12. Jenkins - Update information obtained: 不可用 ago;
  13. pycharm怎么设置成中文版的
  14. mac彩色球转不停,Mac电脑一直在转圈怎么办?
  15. Sentencepiece构建词典
  16. LeetCode-39 - 组合总和
  17. Python多个数组合并
  18. zabbix监控告警表报统计
  19. 【MATLAB】详解 M 文件与 M 函数
  20. 【运维面试】面试官:jenkins你们用过哪些插件?

热门文章

  1. 灰度发布和蓝绿,发布更新部署
  2. GitHub搜索技巧找到好项目
  3. 云计算教程入门视频课件:云计算中心怎么存储数据?
  4. jQuery设置radio默认选中状态及获取选中值
  5. VUE OSS 下载
  6. DynamicProgramming
  7. mate鸿蒙什么时候上市,[财经]华为鸿蒙系统什么时候上市?华为Mate40升级鸿蒙了吗?(2) - 南方财富网...
  8. 2005年第29届ACM ICPC世界总决赛的试题解析
  9. Supermarket | 贪心
  10. mac打开任何来源选项