排序算法

排序算法

排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。

排序算法情况比较

img

img

冒泡排序

基本思想

两个数比较大小,较大的数下沉,较小的数冒起来。

过程

  • 比较相邻的两个数据,如果第二个数小,就交换位置。
  • 从后向前两两比较,一直到比较最前两个数据。最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了。
  • 继续重复上述过程,依次将第2.3...n-1个最小数排好位置。

执行图解如图

img

代码

1
2
3
4
5
6
7
8
9
10
11
public static void BubbleSort(int[] arr){
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr.length-i-1;j++){
if (arr[j] > arr[j + 1]){
int temp = arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
}
}
}
}

优化

问题

数据的顺序排好之后,冒泡算法仍然会继续进行下一轮比较,直到arr.length-1次,但后面的比较没有意义

方案

设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。
这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void BubbleSort(int[] arr){
boolean flag;
for(int i=0;i<arr.length;i++){
flag = false;
for(int j=0;j<arr.length-i-1;j++){
if (arr[j] > arr[j + 1]){
int temp = arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
flag = true;
}
}
// 判断标志位是否为false,如果为false,说明后面的元素已经有序,就直接return
if(!flag){
break;
}
}
}

选择排序

基本思想

在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;
。。。
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。

过程

img

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void SelectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int min = i;//记录最小值的位置
int value = arr[i];//记录最小值的值
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[i] && arr[j] < value) {
min = j;
value = arr[j];
}
}
final int temp = arr[min];
arr[min] = arr[i];
arr[i] = temp;
}
}

插入排序

基本思想

在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

过程

img

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void InsertionSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
} else {
break;
}
}
}
}

希尔排序

基本思想

在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。
然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序。

过程

img

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void HellSort(int[] arr){
int gap = 4;
while(gap>0) {
for (int i = gap; i < arr.length; i+=gap) {
for (int j = i; j > 0; j-=gap) {
if (arr[j] < arr[j - gap]) {
int temp = arr[j - gap];
arr[j - gap] = arr[j];
arr[j] = temp;
} else {
break;
}
}
}
gap/=2;
}

快速排序

基本思想

  • 先从数列中取出一个数作为key值;
  • 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
  • 对左右两个小数列重复第二步,直至各区间只有1个数。

过程

img

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static void FastSort(int[] arr, int low, int high){
if(low>high){
return ;
}
int i = low;
int j = high;
int pivot = arr[i];
while(i<j){
while(i<j && arr[j]>=pivot){
j--;
}
if(i<j){
arr[i] = arr[j];
i++;
}

while(i<j && arr[i]<=pivot){
i++;
}
if(i<j){
arr[j] = arr[i];
j--;
}
}
arr[i] = pivot;
FastSort(arr, low, i-1);
FastSort(arr, i+1, high);
}

归并排序

堆排序

基数排序

感谢您的打赏.