数据结构--排序算法(归并排序&&基数排序&&桶排序)
来源:互联网 发布:数据库管理系统有哪些 编辑:程序博客网 时间:2024/06/07 09:08
在前面我们说了快速排序等排序方法,如有同学想看则请查阅往期博:
插入排序,选择排序:http://blog.csdn.net/sayhello_world/article/details/61927082
冒泡排序,快速排序,鸽巢排序:http://blog.csdn.net/sayhello_world/article/details/63258406
今天我们来说归并排序
归并排序:
递归归并排序:
思路:归并,是将两个或两个以上的有序表合并成一个新的有序表。通过逐层划分,最后逐层向上递归排序,最后得到一个有序的数组。
归并排序的思想及特点:
采用分而治之(divide and conquer)的策略。
小的数据表排序比大的数据表要快。
从两个已经排好序的数据表中构造一个排好序的数据表要比从两个未排序的书记表中构造要少许多步骤。
它是一个稳定的排序算法。
时间复杂度:O(nLogn)
递归实现:
bool Merge_Sort(int array[], int size){int *temp = new int[size];if (temp == NULL)return false;MergeSort(array, temp, 0, size - 1);delete[]temp;return true;}void Merge(int array[],int temp[],int left,int mid, int right){int begin1 = left;int end1 = mid;int begin2 = mid + 1;int end2 = right;int idx = left;//两个区域比较,如果第一个区域的数字小于第二个区域的数字,就让这个数字存到临时空间里while (begin1 <= end1 && begin2 <= end2){if (array[begin1] < array[begin2])temp[idx++] = array[begin1++];elsetemp[idx++] = array[begin2++];}//如果一个区域读取完了 另一个没有读取完 则将后面的数字全部放到临时区域里while (begin1 <= end1)temp[idx++] = array[begin1++];while (begin2 <= end2)temp[idx++] = array[begin2++];}void MergeSort(int array[], int temp[], int left, int right){if (left < right){int mid = left + ((right - left) >> 1);MergeSort(array, temp, left, mid);MergeSort(array, temp, mid + 1, right);Merge(array, temp, left, mid, right);//将临时空间里的数字拷贝到数组里memcpy(array + left, temp + left, sizeof(int)*(right - left + 1));}}
非递归实现:
void Merge(int array[],int temp[],int left,int mid, int right){int begin1 = left;int end1 = mid;int begin2 = mid + 1;int end2 = right;int idx = left;//两个区域比较,如果第一个区域的数字小于第二个区域的数字,就让这个数字存到临时空间里while (begin1 <= end1 && begin2 <= end2){if (array[begin1] < array[begin2])temp[idx++] = array[begin1++];elsetemp[idx++] = array[begin2++];}//如果一个区域读取完了 另一个没有读取完 则将后面的数字全部放到临时区域里while (begin1 <= end1)temp[idx++] = array[begin1++];while (begin2 <= end2)temp[idx++] = array[begin2++];}bool Merge_Sort_Nor(int array[],int size){int *temp = new int[size];if (temp == NULL)return false;int gap = 1;while (gap < size){for (int idx = 0; idx < size; idx += 2 * gap){int left = idx;int mid = left + gap - 1;int right = mid+gap;if (mid >= size)mid = size - 1;if (right >= size)right = size - 1;Merge(array, temp, left, mid, right);}memcpy(array,temp,sizeof(int)*size);gap <<= 1;}delete[]temp;return true;}
以上比较排序就全部完毕。
下面介绍两种非比较排序。
基数排序:
思路:以十进制为例,基数指的是数的位,如个位,十位百位等。先比较个位个位相同的放到一个中,再比较十位,最后比较百位。这样子最后读取出来,就是排序的结果。
有两种形式:
1.Leastsignificant digit(LSD)
短的关键字被认为是小的,排在前面,然后相同长度的关键字再按照词典顺序或者数字大小等进行排序。
2.Mostsignificance digit(MSD)
直接按照字典的顺序进行排序,对于字符串、单词或者是长度固定的整数排序比较合适。
基数排序流程:
将根据整数的最右边数字将其扔进相应的0~9号的篮子里,对于相同的数字要保持其原来的相对顺序(确保排序算法的稳定性),然后将篮子里的数如图所示的串起来,然后再进行第二趟的收集(按照第二位的数字进行收集),就这样不断的反复,当没有更多的位时,串起来的数字就是排好序的数字。
算法分析:
空间复杂度:
采用顺序分配,显然不合适。由于每个口袋都有可能存放所有的待排序的整数。所以,额外空间的需求为10n,太大了。采用链接分配是合理的。额外空间的需求为n,通常再增加指向每个口袋的首尾指针就可以了。在一般情况下,设每个键字的取值范围为d, 首尾指针共计2×radix个,总的空间为O(n+2×radix)。
时间复杂度:
上图示中每个数计有3位,因此执行3次分配和收集就可以了。在一般情况下,每个结点有d 位关键字,必须执行d 次分配和收集操作。
每次分配的代价:O(n)
每次收集的代价:O(radix)
总的代价为:O(d×(n+radix))
代码实现:
//基数排序void RadixSortLSD(int array[], int arraySize){int i, bucket[10], maxVal = 0, digitPosition = 1;//找最大的数 看最大的数有几位for (i = 0; i < arraySize; i++) {if (array[i] > maxVal) maxVal = array[i];}//最大值除以位数要大于0while (maxVal / digitPosition > 0) {int digitCount[10] = { 0 };for (i = 0; i < arraySize; i++)digitCount[array[i] / digitPosition % 10]++;for (i = 1; i < 10; i++)digitCount[i] += digitCount[i - 1];for (i = arraySize - 1; i >= 0; i--)bucket[--digitCount[array[i] / digitPosition % 10]] = array[i];for (i = 0; i < arraySize; i++)array[i] = bucket[i];digitPosition *= 10;}}
桶排序:思想:
桶排序的基本思想是将一个数据表分割成许多buckets,然后每个bucket各自排序,或用不同的排序算法,或者递归的使用bucket sort算法。也是典型的divide-and-conquer分而治之的策略。
步骤:
1.建立一堆buckets;
2.遍历原始数组,并将数据放入到各自的buckets当中;
3.对非空的buckets进行排序;
4.按照顺序遍历这些buckets并放回到原始数组中即可构成排序后的数组。
- 数据结构--排序算法(归并排序&&基数排序&&桶排序)
- 【数据结构】-归并排序,基数排序
- 数据结构之归并排序、基数排序
- 排序算法小结-归并、基数排序
- [C++]数据结构:排序算法Part2----快速排序、归并排序、箱子排序、基数排序
- [C++]数据结构:排序算法Part2----快速排序、归并排序、箱子排序、基数排序
- 排序算法java 二 --基数排序、归并排序
- 算法导论之排序:快速排序、归并排序、计数排序、基数排序、桶排序
- 【更新】排序算法比较:插入排序,冒泡排序,归并排序,堆排序,快速排序,计数排序,基数排序,桶排序
- [数据结构] 归并排序算法
- 数据结构复习-归并排序和基数排序
- 排序算法复习(Java实现)(二): 归并排序,堆排序,桶式排序,基数排序
- 排序算法复习(Java实现)(二): 归并排序,堆排序,桶式排序,基数排序
- 排序算法复习(Java实现)(二): 归并排序,堆排序,桶式排序,基数排序
- 算法-排序-归并排序和基数排序(排序总结)
- 基础数据结构算法_计数排序,基数排序,桶排序
- 希尔排序,基数排序,归并排序
- 经典排序算法设计与分析(插入排序、冒泡排序、选择排序、shell排序、快速排序、堆排序、分配排序、基数排序、桶排序、归并排序)
- Unity3D学习:射击小游戏——飞碟世界
- PRD、MRD与BRD
- List 取 Array
- 无法打开包括文件:“GLES2/gl2.h”: No such file or directory
- JAVA对象JSON数据互相转换的四种常见情况
- 数据结构--排序算法(归并排序&&基数排序&&桶排序)
- 算法-1-堆和队列-汇总(持续更新)-目录呈现
- L2-005. 集合相似度(set集合)
- Webstorm 创建文件使用模板自动生成代码
- Linux 编译 OpenCV 出现 ‘cv::imread(std::__cxx11:: 错误的解决方案
- 【ORACLE】逗号分隔的字符串的应用
- 剑指offer-二叉树的镜像-php
- c#上Redis示例<一.写>
- c++上机实验3 个人所得税计算器