[内排序]八大经典排序合集

文章目录

  • 1 排序的基本概念
    • 1.1 什么是排序
    • 1.2 排序的稳定性
    • 1.3 内排序和外排序
  • 2 插入排序
    • 2.1 直接插入排序
      • 1. 排序思路
      • 2. 直接插入排序实例
      • 3. 排序算法
      • 4. 算法分析
      • 5. 折半插入排序 / 二分插入排序
        • 5.1 排序思路
        • 5.2 排序算法
      • 5.3 算法分析
    • 2.2 希尔排序
      • 1. 排序思路
      • 2. 希尔排序实例
      • 3. 排序算法
      • 4. 算法分析
  • 3 交换排序
    • 3.1 冒泡排序
      • 1. 排序思路
      • 2. 冒泡排序实例
      • img
      • 3. 排序算法
      • 4. 算法分析
      • 5. 改进的冒泡排序算法
    • 3.2 快速排序
      • 1. 排序思路
      • 2. 快速排序实例
      • 3. 排序算法
      • 4. 算法分析
  • 4 选择排序
    • 4.1 直接选择排序
      • 1. 排序思路
      • 2. 直接选择排序实例
      • 3. 排序算法
      • 4.算法分析
    • 4.2 堆排序
      • 1. 排序思路
      • 2. 直接选择排序实例
      • 3. 排序算法
      • 4.算法分析
  • 5 归并排序
      • 1. 排序思路
      • 2. 归并排序实例
      • 3. 排序算法
      • 4. 算法分析
  • 6 基数排序
      • 1. 排序思路[#](#619425620)
      • 2. 基数排序实例
      • 3. 排序算法
      • 4. 算法分析
  • 7 各种内排序方法的比较和选择
      • 1. 各种排序方法的性能比较
      • 2. 选择排序方法应综合考虑下列因素:
      • 3. 总结

1 排序的基本概念

假定排序的数据是由一组元素组成的表,而元素由若干个数据项组成,其中有一项可用来标识该元素,称为关键字项,其值称为关键字。关键字可用作排序运算的依据。

1.1 什么是排序

所谓排序,就是整理表中的元素,使之按关键字递增或递减的顺序排列。

1.2 排序的稳定性

当待排序元素的关键字各不相同时,排序的结果是唯一的,否则排序的结果不一定唯一。

如果待排序的表中,存在多关键字相同的元素,经过排序后这些具有相同关键字的元素之间的相对次序保持不变,则称这种排序方法是稳定的;反之,若具有相同关键字的元素之间的相对次序发生变化,则称这种排序方法是不稳定的

注意,排序算法的稳定性是针对所有输入实例而言的。也就是说,在所有可能的输入实例中,只要有一个实例使得算法不满足稳定性要求,则该排序算法就是不稳定的。

1.3 内排序和外排序

在排序过程中,若整个表都是放在内存中处理,排序时不涉及内、外存数据的交换,则称之为内排序;反之,若排序过程中要进行内。外存数据的交换,则称之为外排序

内排序适用于元素个数不是很多的小表,外排序则适用于元素个数很多,不能一次将全部元素放入内存的大表。

按所用的策略不同,排序方法还可以分为需要关键字比较和不需要关键字比较两类。需要关键字比较的排序方法有插入排序。选择排序。交换排序和归并排序;不需要关键字比较的排序方法有基数排序。

img

图1.1 排序的分类

2 插入排序

插入排序基本思想:每次将一个待排序的元素,按其关键字大小插入到已经排好序的子表中的适当位置,直到全部元素插入完成为止。

2.1 直接插入排序

1. 排序思路

假设待排序的元素存放在数组 Data[0…n-1] 中,排序过程中的某一时刻,Data 被划分成两个子区间 Data[0…i-1] 和 Data[i…n-1](刚开始时 i=1,有序区只有 Data[0] 一个元素),其中,前一个子区间是已排好序的有序区,后一个子区间则是当前未排序的部分,称其为无序区。直接插入排序的一趟操作是将当前无序区的开头元素 Data[i] (1 <= i <= n-1)插入到有序区 Data[0…i-1] 中适当的位置上,使 Data[0…i] 变为新的有序区,如图2.1所示。这种方法通常称为增量法,因为它每趟操作使有序区增加一个元素。

img

说明:直接插入排序每趟产生的有序区并一定是全局有序区,也就是说有序区中的元素并不一定放在其最终的位置上。当一个元素在整个排序结束前就已经放在其最终的位置上,称为归位。

2. 直接插入排序实例

设待排序的表有 10 个元素,其关键字为 {9,8,7,6,5,4,3,2,1,0}。以下为直接插入排序的排序过程:

img

图中用方括号表示每趟操作后的有序区。每趟向有序区中插入一个元素(用方框表示),并保持有序区中的元素仍有序。

3. 排序算法

public class InsertSort {public static void insertSort(int[] Data) {int temp , j;for(int i = 0; i < Data.length; i++) {temp = Data[i];j = i-1;                        //从右向左在有序区Data[0..i-1]中找Data[i]的插入位置while(j >= 0 && temp < Data[j]) {Data[j+1] = Data[j];        //将大于Data[i]的元素后移j--;}Data[j+1] = temp;                //在j+1处插入Data[i]}}public static void main(String[] args) {int[] Data = {9,8,7,6,5,4,3,2,1,0};insertSort(Data);System.out.println("直接插入排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}
}

4. 算法分析

时间复杂度:O(n2);

空间复杂度:O(1);

稳定性:稳定;

复杂性:简单。

5. 折半插入排序 / 二分插入排序

5.1 排序思路

直接插入排序将无序区中开头元素 Data[i](1 <= i <= n-1)插入到有序区 Data[0…i-1]中,此时可以采用折半查找方法先在 Data[0…i-1] 中找到插入的位置,再通过移动元素进行插入。

在Data[low…high](初始时 low=0,high=i-1)中采用折半查找插入 Data[i] 的位置为 Data[high+1],再将 Data[high+1…i-1] 中的元素后移一个位置,并置 Data[high+1] = Data[i]。

说明:和直接插入排序一样,折半插入排序每趟产生的有序区并不一定是全局有序区。

5.2 排序算法

public class HalfInsertSort {public static void halfInsertSort(int[] Data) {int low , high , mid;int temp;for(int i = 1; i < Data.length; i++) {temp = Data[i];                //将Data[i]保存在temp中low = 0;high = i-1;while( low <= high) {        //在Data[low..high]中折半查找有序插入的位置mid = (low+high) / 2;    //取中间位置if(temp < Data[mid]) {high = high-1;        //插入点在左半区}else {low = mid + 1;        //插入点在右半区}}for(int j = i-1; j >= high+1; j--) {Data[j+1] = Data[j];    //元素后移}Data[high+1] = temp;        //插入在Data[high+1]位置}}public static void main(String[] args) {int[] Data = {9,8,7,6,5,4,3,2,1,0};halfInsertSort(Data);System.out.println("折半插入排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}
}

5.3 算法分析

从上述算法中看到,当初始数据序列为正序时,关键字的比较次数并不能减少;当初始数据序列为反序时,关键字的比较次数也不会增加。

折半插入排序的元素移动次数与直接插入排序相同,不同的仅是变分散移动为集合移动。

就平均性能而言,折半查找优于顺序查找,所以折半插入排序优于直接插入排序。

时间复杂度为:O(n2);

空间复杂度为:O(1);

稳定性:稳定;

复杂性:简单。

2.2 希尔排序

1. 排序思路

先取定一个小于数组长度 Data.length 的整数 gap(gap = Data.length / 2)作为第一个增量,把表的全部元素分成 gap 个组,所有相互之间距离为 gap 的倍数的元素放在同一个组中,在各组内进行直接插入排序;然后,减小增量 gap(gap = gap /2),重复上述的分组和排序过程,直至增量减小为 0,即所有元素放在同一组中进行直接插入排序。

说明:希尔排序每趟并不产生有序区,在最后一趟排序结束前,所有元素并不一定归位。但是每趟排序完成后,数据越来越接近有序。

2. 希尔排序实例

设待排序的表有 10 个元素,其关键字为 {9,8,7,6,5,4,3,2,1,0}。以下为直接插入排序的排序过程:

img

第一趟排序时,d = 5 ,整个表被分成 5 组:(9,4),(8,3),(7,2),(6,1),(5,0),各组采用直接插入排序方法变成有序的,即结果分别为(4,9),(3,8),(2,7),(1,6)(0,5)。

第二趟排序时,d = 2,整个表分为两组:(4,2,0,8,6)和(3,1,9,7,5),各组采用直接插入排序方法变成有序的,即结果分别为(0,2,4,6,8)和(1,3,5,7,9)。

第三趟排序时,d = 1,整个表为一组,采用直接插入排序方法使整个数列有序,最终结果为(0,1,2,3,4,5,6,7,8,9)。

3. 排序算法

public class ShellSort {public static void shellSort(int[] Data) {int gap = Data.length / 2;                //增量置初值int temp = 0 , j = 0;while(gap > 0) {for(int i = gap; i < Data.length; i++) {    //对所有相隔gap位置的元素组采用直接插入排序temp = Data[i];j = i - gap;while(j >= 0 && temp < Data[j]) {        //对相隔gap位置的元素组进行排序Data[j+gap] = Data[j];j -= gap;}Data[j+gap] = temp;}gap /= 2;                            //减小增量}}public static void main(String[] args) {int[] Data = {9,8,7,6,5,4,3,2,1,0};shellSort(Data);System.out.println("希尔排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}
}

4. 算法分析

时间复杂度:O(n1.3);

空间复杂度:O(1);

稳定性:不稳定;

复杂性:较复杂。

3 交换排序

3.1 冒泡排序

1. 排序思路

通过无序区中相邻元素间关键字的比较和位置的交换,使关键字最小的元素如气泡一般逐渐往上“漂浮”直至“水面”。整个算法是从最下面的元素开始,对每两个相邻的关键字进行比较,且使关键字较小的元素换至关键字较大的元素之上,使得经过一趟冒泡排序后,关键字最小的元素到达最上端。接着,再在剩下的元素中找关键字次小的元素,并把它交换到第二个位置上。依次类推,一直到所有元素都有序为止。

img
  说明:冒泡排序每趟产生的有序区一定是全局有序区,也就是说每趟产生的有序区中所有元素都归位了。

2. 冒泡排序实例

设待排序的表有 10 个元素,其关键字为 {9,8,7,6,5,4,3,2,1,0}。以下为冒泡排序的排序过程:

每次从无序区中冒出一个关键字最小的元素(用方框表示)并将其定位。

img

3. 排序算法

public class BubbleSort {public static void bubbleSort(int[] Data) {int temp = 0;for(int i = 0; i < Data.length-1; i++) {for(int j = Data.length-1 ; j > i; j--) {    //比较,找出本趟关键字最小的元素if(Data[j] < Data[j-1]) {temp = Data[j];                //Data[j-1]与Data[j]进行交换,将关键字最小的元素前移Data[j] = Data[j-1];Data[j-1] = temp;}}}}public static void main(String[] args) {int[] Data = {9,8,7,6,5,4,3,2,1,0};bubbleSort(Data);System.out.println("冒泡排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}}

4. 算法分析

时间复杂度为:O(n2);

空间复杂度为:O(1);

稳定性:稳定;

复杂性:简单。

5. 改进的冒泡排序算法

在有些情况下,在第 i (i < n-1)趟时就已经排好序了,但算法仍执行后面几趟的比较。实际上,一旦算法中某一趟比较时没有出现任何元素交换,说明已排好序了,就可以结束本算法。为此,改进冒泡排序算法如下:

public class ImproveBubbleSort {public static void improveBubbleSort(int[] Data) {boolean exchange;int temp = 0;for(int i = 0; i < Data.length-1; i++) {exchange = false;for(int j = Data.length-1; j > i; j--) {    //比较,找出本趟关键字最小的元素if(Data[j] < Data[j-1]) {temp = Data[j];                //Data[j-1]与Data[j]进行交换,将关键字最小的元素前移Data[j] = Data[j-1];Data[j-1] = temp;exchange = true;}}if(!exchange)                        //本趟没有发生交换,中途结束算法return;}}public static void main(String[] args) {int[] Data = {9,8,7,6,5,4,3,2,1,0};improveBubbleSort(Data);System.out.println("改进冒泡排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}
}

3.2 快速排序

1. 排序思路

在待排序的 n 个元素中任取一个元素(通常取第一个元素)作为基准,把该元素放入适当的位置后,数据序列被此元素分成两部分,所有关键字比该元素关键字小的元素放置在前一部分,所有关键字比该元素关键字大的元素放置在后一部分,并把该元素排在这两部分的中间(称该元素归位),这个过程称做一趟快速排序,之后对所有划分出来的两部分分别重复上述过程,直至每部分内只有一个元素或为空为止。

img

说明:快速排序每趟仅将一个元素归位。

2. 快速排序实例

设待排序的表有 10 个元素,其关键字为 {6,8,7,9,0,1,3,2,4,5}。以下为快速排序的排序过程:

其排序过程如图 3.4 所示(最后结果图(g)称为快速排序递归树)。第 1 趟是以 6 为基准将整个区间分为(5,4,2,3,0,1)和(9,7,8)两个子区间,并将 6 归位;对于每个子区间,又进行同样的排序,直到该子区间只有一个元素或不存在元素为止。

img

3. 排序算法

public class QuickSort {public static void quickSort(int[] Data , int s , int t) {int i = s , j = t;                        //对Data[s]至Data[t]的元素进行快速排序int temp = 0;if(s < t) {                                //区间内至少存在两个元素的情况temp = Data[s];                        //用区间的第1个元素作为基准while(i != j) {                        //从区间两端交替向中间扫描,直至i = j为止while(j > i && Data[j] >= temp)j--;                        //从右向左扫描,找第1个小于temp的元素Data[j]Data[i] = Data[j];                //找到这样的Data[j],Data[i]与Data[j]交换while(i < j && Data[i] <= temp)i++;                        //从左向右扫描,找第1个大于temp的元素Data[j]Data[j] = Data[i];                //找到这样的Data[i],Data[i]与Data[j]交换}Data[i] = temp;quickSort(Data, s, i-1);            //对左区间递归排序quickSort(Data, i+1, t);            //对右区间递归排序}}public static void main(String[] args) {int[] Data = {6,8,7,9,0,1,3,2,4,5};quickSort(Data, 0, Data.length-1);System.out.println("快速排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}
}

4. 算法分析

时间复杂度:O(nlog2n);

空间复杂度:O(log2n);

稳定性:不稳定;

复杂性:较复杂。

4 选择排序

4.1 直接选择排序

1. 排序思路

第 i 趟排序开始时,当前有序区和无序区分别为 Data[0…i-1] 和 Data[i…n-1](0 <= i < n-1),该趟排序是从当前无序区中选出关键字最小的元素 Data[k],将它与无序区的第 1 个元素 Data[i] 交换,使 Data[0…i] 和 Data[i+1…n-1] 分别变为新的有序区和新的无序区,如图4.1所示。因为每趟排序均使有序区中增加一个元素,且有序区中的元素关键字均不大于无序区中元素的关键字,即第 i 趟排序之后,Data[0…i] 中的关键字小于 Data[i+1…n-1] 中的所有关键字,所以进行 n-1 趟排序之后有 Data[0…n-2] 中的所有关键字小于等于 Data[n-1],也就是说,经过 n-1 趟排序之后,整个表 Data[0…n-1] 递增有序。

img 说明:直接选择排序每趟产生的有序区一定是全局有序区,也就是说每趟产生的有序区中所有元素都归位了。

2. 直接选择排序实例

设待排序的表有 10 个元素,其关键字为 {6,8,7,9,0,1,3,2,4,5}。以下为直接选择排序的排序过程:

每趟选择出一个元素(带方框者)。

img

3. 排序算法

public class SelectSort {public static void selectSort(int[] Data) {int k = 0;int temp = 0;for(int i = 0; i < Data.length-1; i++) {     //做第i趟排序k = i;for(int j = i+1; j < Data.length; j++) { //在当前无序区Data[i..n-1]中选最小的Data[k]if(Data[j] < Data[k])k = j;                             //k记下目前找到的最小关键字所在的位置}if(k != i) {                             //交换Data[i]和Data[k]temp = Data[i];Data[i] = Data[k];Data[k] = temp;}}}public static void main(String[] args) {int[] Data = {6,8,7,9,0,1,3,2,4,5};selectSort(Data);System.out.println("直接选择排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}}

4.算法分析

时间复杂度:O(n2);

空间复杂度:O(1);

稳定性:不稳定;

复杂性:简单。

4.2 堆排序

1. 排序思路

堆排序是一种树形选择排序方法,它的特点是,在排序过程中,将 Data[0…n-1] 看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的元素。

堆排序的排序过程中每次挑选最大元素归位,如图4.3所示。挑选最大元素的方法是将数组中存储的数据看成是一棵完全二叉树,利用完全二叉树中双亲节点和孩子节点之间的内在关系来选择关键字最大的元素。具体的做法是:把待排序的表的关键字存放在数组Data[0…n-1] 之中,将 Data 看做一棵二叉树,每个节点表示一个元素,源表的第一个元素Data[0] 作为二叉树的根,以下各元素 Data[1…n-1] 依次逐层从左到右顺序排列,构成一棵完全二叉树,节点 Data[i] 的左孩子是 Data[2i+1],右孩子是 Data[2i+2],双亲是 Data[(i+1)/2-1]。

img
说明:堆排序每趟产生的有序区一定是全局有序区,也就是说每趟产生的有序区中所有元素都归位了。

2. 直接选择排序实例

设待排序的表有 10 个元素,其关键字为 {6,8,7,9,0,1,3,2,4,5}。以下为堆排序的排序过程:

其初始状态如图4.4(a)所示,通过第一个 for 循环调用 sift() 产生的初始堆如图4.4(b)所示,这时 Data 中关键字序列为{9,8,7,6,5,1,3,2,4,0}。

img
堆排序的排序过程如图4.5所示,每输出一个元素,就对堆进行一次筛选调整。

img

3. 排序算法

public class HeapSort {public static void heapSort(int[] Data , int n) {int temp = 0;for(int i = (n+1)/2-1; i >= 0; i--)    //循环建立初始堆,第一个双亲节点的位置序号为(n+1)/2-1sift(Data , i , n-1);for(int i = n-1; i >= 1; i--) {        //进行n-1趟堆排序,每一趟堆排序的元素个数减1temp= Data[0];                    //将最后一个元素同当前区间内Data[0]对换Data[0] = Data[i];Data[i] = temp;sift(Data , 0 , i-1);            //筛选Data[0]节点,得到i个节点的堆}}// 调整堆private static void sift(int[] Data, int low, int high) {int place = 2 * low + 1;            //该节点的左孩子在数组中的位置序号int temp = Data[low];                //保存当前节点while(place <= high) {if(place+1 <= high && Data[place] < Data[place+1])    //若右孩子较大,则把place指向右孩子place++;if(temp < Data[place]) {Data[low] = Data[place];    //将Data[place]调整到双亲节点位置上low = place;                //修改low和place值,以便继续向下筛选place = 2 * low+1;} elsebreak;                        //筛选结束}Data[low] = temp;                    //被筛选节点的值放入最终位置}public static void main(String[] args) {int[] Data = {6,8,7,9,0,1,3,2,4,5};heapSort(Data,Data.length);System.out.println("堆排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}}

4.算法分析

时间复杂度:O(nlog2n);

空间复杂度:O(1);

稳定性:不稳定;

复杂性:较复杂。

5 归并排序

1. 排序思路

归并排序是多次将两个或两个以上的有序表合并成一个新的有序表。最简单的归并排是直接将两个有序的子表合并成一个有序的表即二路归并。

将 Data[0…n-1] 看成是 n 个长度为 1 的有序序列,然后进行亮亮归并,得到 [n/2] 个长度为 2(最后一个有序序列的长度可能为 1)的有序序列,再进行两两归并,得到 [n/4] 个长度为 4(最后一个有序序列的长度可能小于 4)的有序序列,…… ,直到得到一个长度为 n 的有序序列。

说明:归并排序每趟产生的有序区只是局部有序的,也就是说在最后一趟排序结束前,所有元素并不一定归位了。

2. 归并排序实例

设待排序的表有 10 个元素,其关键字为 {18,2,20,34,12,32,6,16}。以下为归并排序的排序过程:

采用二路归并排序时,需要进行 3 趟归并排序,其过程如图5.1所示。第 1 趟将每两个各含有一个元素的子表归并成一个新表,如将 {18} 和 {2} 排好序变为 {2,18}。第 2 趟将每两个各含有两个元素的子表归并成一个新表,如将 {2,18} 和 {20,34} 归并为{2,18,20,34}。第 3 趟将每两个各含有 4 个元素的子表归并成一个新表,产生最终有序表。

img

3. 排序算法

public class MergeSort {/*** 自底向上的二路归并算法* @param Data*/public static void mergeSort(int[] Data) {for(int i = 1; i < Data.length; i = 2*i) {    //进行log2n趟归并mergePass(Data , i , Data.length);}}/*** 对整个表进行一趟归并* @param Data* @param len    子表的长度* @param n        整个表的长度*/private static void mergePass(int[] Data, int len, int n) {int  i = 0;for(i = 0; i + 2*len - 1 < n; i += 2*len) {        //归并len长的两个相邻子表merge(Data , i , i+len-1 , i+2*len-1);}if(i+len-1 < n) {                                //余下两个子表,后者长度小于lenmerge(Data , i , i+len-1 , n-1);            //归并这两个子表}}/*** 实现两个子表在同一个表中的一次归并* @param Data* @param low    第一个子表的开始* @param mid    第一个子表的结尾* @param high    第二个子表的结尾,第二个子表的开始为mid+1*/private static void merge(int[] Data, int low, int mid, int high) {int[] num = new int[Data.length];    //暂存数组int i = low;    //第一个子表的开始下标int j = mid+1;    //第二个子表的开始下标int k = 0;        //暂存表的下标while( i <= mid && j <= high) {    //在第一个子表和第二个子表均为扫描完时循环if(Data[i] <= Data[j]) {    //将第一个子表中的元素放入暂存表numnum[k] = Data[i];i++;k++;} else {                    //将第二个子表中的元素放入暂存表numnum[k] = Data[j];j++;k++;}}while(i <= mid) {                //将第一个子表剩余部分复制到暂存表numnum[k] = Data[i];i++;k++;}while(j <= high) {                //将第二个子表剩余部分复制到暂存表numnum[k] = Data[j];j++;k++;}for(k = 0 , i = low; i <= high; k++ , i++) {    //将暂存表复制到源表中Data[i] = num[k];}}public static void main(String[] args) {int[] Data = {18,2,20,34,12,32,6,16};mergeSort(Data);System.out.println("归并排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}
}

4. 算法分析

时间复杂度:O(nlog2n);

空间复杂度:O(n);

稳定性:稳定;

复杂性:较复杂。

6 基数排序

1. 排序思路#

基数排序有两种:最低位优先(LSD)和最高位优先(MSD)。最低位优先的过程是:先按最低位的值对元素进行排序,在此基础上,再按次低位进行排序,以此类推,由低位向高位,每趟都是根据关键字的一位并在前一趟的基础上对所有元素进行排序,直至最高位。

说明:基数排序每趟并不产生有序区,也就是说在最后一趟排序结束前,所有的元素并不一定归位了。

2. 基数排序实例

设待排序的表有 10 个元素,其关键字为 {18,2,20,34,12,32,6,16}。以下为堆排序的排序过程:

先按个位数进行排序,再按十位数进行排序。

img]

3. 排序算法

public class RadixSort {public static void radixSort(int[] Data){int[][] gather = new int[10][Data.length];    //存放某位上数相同值的那一些数,如15 ,25int[] sameNumSize = new int[10];               //存放某位相同值的那一些数的个数int some=0;        //总的收集次数int sub = 0;      //数组Data的下标int n=1;          //取低位上的值时的除数,如取个数时n=1,取十位时n=10while(some < maxSize(Data)) {for(int i = 0; i < Data.length; i++) {    //从个位开始分配int remain = (Data[i] / n) % 10;    //取某位上的数gather[remain][sameNumSize[remain]] = Data[i];    //将某位上数相同值的那一些数存放在二维数组gather中sameNumSize[remain]++;                //相同值的那一些数的个数加1}for(int i = 0; i < 10; i++) {    //将分配结束的数收集到源数组中if(sameNumSize[i] != 0) {for(int j = 0; j < sameNumSize[i]; j++) {Data[sub] = gather[i][j];sub++;}sameNumSize[i] = 0;        //置空,以便下次分配时使用}}sub = 0;    //下标置0n *= 10;      //取次低位some++;      //收集次数加1}}/*** 求数组中最大数的长度* @param arr* @return 最大长度*/public static int maxSize(int[] arr) {int temp = arr[0];for(int i = 1;i < arr.length; i++) {if(temp < arr[i]) {temp = arr[i];}}return String.valueOf(temp).length();}public static void main(String[] args) {int[] Data = {75,23,98,44,57,12,29,64,38,82};radixSort(Data);System.out.println("基数排序的结果:");for(int i = 0; i < Data.length; i++) {System.out.print(Data[i]+" ");}}
}

4. 算法分析

时间复杂度:O(d(n+r));

空间复杂度:O®;

稳定性:稳定;

复杂性:较复杂。

7 各种内排序方法的比较和选择

1. 各种排序方法的性能比较

img]

图7.1 各种排序方法的性能比较

2. 选择排序方法应综合考虑下列因素:

(1)待排序的元素数目 n(问题规模);

(2)元素的大小(每个元素的规模);

(3)关键字的结构及其初始状态;

(4)对稳定性的要求;

(5)语言工具的条件;

(6)存储结构;

(7)时间和空间复杂度。

3. 总结

(1)若 n 较小(如 n <= 50),可采用直接插入和直接选择排序;

(2)若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序;

(3)若 n 较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序;

(4)若要将两个有序表组合成一个新的有序表,最好的方法是归并排序方法;

(5)若 n 很大,元素的关键字位数较少且可以分解时,采用基数排序较好。

原文地址:https://www.cnblogs.com/cao-lei/p/6742815.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么解决机械革命笔记本蓝屏问题

1、重启电脑&#xff0c;出现logo界面后连续按F2键直到打开bios&#xff0c;接着切换至“Advanced”&#xff0c;将光标移至“OS Support”选项&#xff0c;并将后面数值调成“Others”。 2、接下来将光标移至“SATA Device”选项&#xff0c;将硬盘模式调成“AHCI”。 3、最后…

bootsqm.dat是什么文件 bootsqm.dat可以删除吗

我们经常会发现系统C盘里面有一个bootsqm.dat文件&#xff0c;这个文件占用空间还是蛮大的&#xff0c;因此有些用户想要知道bootsqm.dat是什么文件?bootsqm.dat可以删除吗?其实这两个问题很简单&#xff0c;下面就由小编来告诉大家bootsqm.dat是什么文件及其能不能删除吧! …

win10笔记本打开只有飞行模式的解决方法

方法一&#xff1a; 1、按下“winr”打开运行&#xff0c;输入“regedit”&#xff0c;依次展开到“HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesNdisuio”&#xff0c;查看其“DisplayName”键值是“NDISUsermode I/O Protocol”如缺损&#xff0c;可新建; 2、在右边…

笔记本win10系统连接wifi显示无Internet安全如何解决

方法一&#xff1a; 1、进入设置&#xff0c;找到“网络和Internet”&#xff0c;双击; 2、找到“更改适配器选项”&#xff0c;双击; 3、双击进入你的WLAN; 4、找到页面下方“属性”&#xff0c;单击; 5、(1)如果在项目列表里出项“WifiMasterNATDriver”是选中状态的话&…

win10 更新后不能切换输入法怎么办 win10输入法切换不了怎么解决

有win10用户说他在更新完系统后&#xff0c;在切换输入法的时候发现竟然切换不了无法切换&#xff0c;都不知道该怎么办了&#xff0c;这个小问题也是常有的&#xff0c;那么win10更新后不能切换输入法怎么办呢&#xff0c;下面小编给大家分享win10输入法切换不了的解决方法。 …

解决Java8 分组groupingBy 后排序不变的问题

在工作中遇到了java8 Stream groupBy 分组排序失效的问题 在此记录一下解决方案 预期效果&#xff1a; 按照年纪倒序并分组 实际结果&#xff1a;返回的数据是杂乱无章&#xff0c;并没有按照年纪倒序 示例代码如下&#xff1a; import java.util.Comparator; import java.u…

win8无线网络受限怎么办 win8网络受限的解决方法

很多时候&#xff0c;我们的用户经常会遇到win8无线网络受限的问题&#xff0c;从而导致电脑无法上网&#xff0c;这可如何是好呢?win8无线网络受限怎么办呢?下面&#xff0c;就给大家介绍几种win8无线网络受限的解决方法&#xff0c;提供给大家参考。 一、检测无线网络是否…

教你win10怎么设置环境变量

电脑在运行一些程序的时候&#xff0c;我们经常都会需要修改系统的环境变量&#xff0c;添加路径&#xff0c;尤其是java运行环境配置和Android环境配置。为此&#xff0c;这里小编就以win10为例给大家讲解一下如何设置环境变量。 win10系统以界面优美、开机速度快、功能强大等…

告诉你win10自带录屏怎么使用

win10自带录屏怎么使用呢一些游戏玩家之前都是下载第三方屏幕录像软件录像&#xff0c;升级win10过后发现win10系统自带录屏功能&#xff0c;但是又不知道在哪打开?针对这个问题&#xff0c;我给大家带来了详细的操作步骤&#xff0c;一起来看看吧 不得不说win10系统实在是太…

Content-Type详解SpringBoot中如何根据Content-Type解析数据

文章目录Content-Type详解Content-Type是什么&#xff1f;Content-Type的格式Post请求中常见的Content-Type类型的结构SpringBoot中如何根据Content-Type解析数据一、接收get请求二、接收Post请求总结&#xff1a;Content-Type详解 Content-Type是什么&#xff1f; 在HTTP协议…

U盘重装win7系统教程

第一步 先在浏览器搜索云骑士官网&#xff1a;www.yunqishi.net 在官网上下载云骑士装机大师软件&#xff0c;下载好以后打开云骑士装机大师&#xff0c;打开后云骑士会自动配置用户的电脑信息&#xff0c;选择启动U盘界面。并且在电脑上插入U盘。 2 第二步 接着就进入了选择系…

【编程技巧】Stream流之list转map、分组取每组第一条

前言 JDK1.8推出的stream流能极大的简化对集合的操作&#xff0c;让代码更美观&#xff0c;老规矩&#xff0c;直接上代码。 一、list转map 取list中对象的某个属性作为唯一key&#xff0c;对象作为value形成一个map集合&#xff0c;能够便于在后续业务中取值而不用遍历list…

Java中String类常用方法详解: concat(),format(),charAt(),indexOf(),substring(),compareTo(),split(),replaceAll

文章目录1.连接字符串 concat()2.创建格式化对象 format()3.获取字符串某一位置字符 charAt()4.获取字符串的长度 length()5.查找子串在字符串中的位置 indexOf()6.截取字符串的子串 substring()7.字符串比较 compareTo()8.字符串大小写转换 toLowerCase()【大写换小写】 toUpp…

手把手教你dns服务器未响应导致无法上网怎么办

dns服务器未响应怎么办&#xff1f;其实每个问题都是有着相对应的原因外加解决方法的&#xff0c;我这刚好就有一篇关于如何解决dns服务器未响应的方法&#xff0c;现在就来分享给各位小伙伴们哈~ 不知道小伙伴们在使用电脑进行上网的时候&#xff0c;有木有遇到过这样子的一个…

win7发现不了无线网络怎么办 win7发现不了无线网络的解决办法

今天来跟各位说说win7发现不了无线网络怎么办。 1.我们单击右下角的无线网络以打开网络和共享中心。 2.单击“更改适配器设置”。 3.在“网络连接”窗口中&#xff0c;如果网络连接中的无线网络显示为灰色&#xff0c;则右键单击“启用”。 4.在网络连接中没有无线网络连接&…

win7分辨率不能调怎么办 win7系统分辨率不能调的解决方案

win7分辨率不正常怎么回事?分辨率为什么不能调?win7分辨率不能调是什么原因?怎么来解决win7分辨率不能调的问题?现在小编就分享一篇关于win7系统分辨率不能调的解决方案。 分辨率对系统来说是相当重要的&#xff0c;这关系到系统桌面屏幕的清晰度&#xff0c;如果调得不好…

Mybatis-Plus字段策略FieldStrategy详解

文章目录一、官方文档二、字段策略介绍1、FieldStrategy作用2、FieldStrategy类型3、FieldStrategy配置全局策略配置单字段策略配置三、实战说明1.默认策略 - NOT_NULL2.忽略判断-IGNORED3.从不处理-NEVER4.字符不为空-NOT_EMPTY5.跟随全局-DEFAULT总结一、官方文档 Mybatis-P…

任意门怎么用团发_衣柜门选用什么材料好?小编在这里告诉你

衣柜是美观家庭必不可少的&#xff0c;它我们的空间看起来更整洁。但是衣柜的材料值得我们好好考虑一下。衣柜门有哪些材质1、铝合金铝合金材质的衣柜门在日常生活中比较常见&#xff0c;使用得比较多。这是因为其环保性能比较好&#xff0c;而且十分耐用&#xff0c;还具有较强…

Google Gson API 介绍与使用

文章目录Gson基本操作Gson 概述与下载Gson (反)序列化 Java 对象JsonElement Json 元素JsonObject Json 对象JsonArray Json 数组JsonParser Json 解析GsonBuilder 构建 GsonJsonElement的简单说明JsonElement&#xff1a;JsonPrimitive&#xff1a;JsonNull:JsonArray:JsonObj…

光功率 博科交换机_如何将交换机40G QSFP+与10G SFP+端口互连?

随着40G以太网的到来&#xff0c;许多企业用户开始充分利用当前的10G网络设备升级到40G网络&#xff0c;具体来说也就是如何将带有QSFP端口的40G交换机与现有带SFP端口的10G设备(交换机和服务器)搭配使用的问题。在本篇文章中&#xff0c;易天光通信(ETU-LINK)将分享三种常见的…