glmapper

算法-排序算法思想及实现

字数统计: 1.5k阅读时长: 6 min
2018/11/10 Share

排序算法主要有:插入排序,选择排序,冒泡排序,希尔排序,归并排序,快速排序,堆排序。这里的排序指的是内部排序,也就是基于内存的排序,基于内存的排序是基于大O模型的,可以使用大O模型来衡量算法的性能
摘自我自己的博客园:http://www.cnblogs.com/myadmin/p/5821158.html 中的部分排序算法。

插入排序

基本思想:每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。

1
2
3
4
原始:4 3 1 2
1) 3 4 1 2
2) 1 3 4 2
3) 1 2 3 4

核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 插入排序
*/
public static int[] insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int index = i;// index当前扫描到的元素下标
int temp = arr[i];
// 寻找插入的位置
while (index > 0 && temp < arr[index - 1]) {
arr[index] = arr[index - 1];
index--;
}
arr[index] = temp;
}
return arr;
}

选择排序

基本思想:从所有序列中先找到最小的,然后放到第一个位置。之后再看剩余元素中最小的,放到第二个位置……以此类推,就可以完成整个的排序工作了。可以很清楚的发现,选择排序是固定位置,找元素。相比于插入排序的固定元素找位置,是两种思维方式。

1
2
3
4
5
6
7
8
9
3 2 1 4 6 5

初始化索引位置为0
寻找最小值所在位置交换:1 2 3 4 6 5

初始化索引位置为1
寻找最小值所在位置交换:1 2 3 4 6 5

依次类推!

核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 选择排序
*/
public static int[] selectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int minVal = arr[i];
int index = i;
for (int j = i + 1; j < arr.length; j++) {// 找到最小元素
if (arr[j] < minVal) {
minVal = arr[j];
index = j;
}
}
arr[index] = arr[i];
arr[i] = minVal;
}
return arr;
}

冒泡排序

基本思想:原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换。
核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 冒泡排序
*
* @param arr
* 输入的待排数组
* @return 返回排序号的数组
*/
public static int[] bubbleSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 1; j < arr.length; j++) {
if (arr[j - 1] > arr[j]) {
int temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}

希尔排序

基本思想:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止。(下图来自百度图片)

核心代码:

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
/**
* 希尔排序
*
* @author sgl
*
*/
public class ShellSort {

public static int[] shellSort(int[] arr) {
int step = arr.length / 2;// 初始步长

while (1 <= step) {
for (int i = step; i < arr.length; i++) {
if (arr[i] < arr[i - step]) {
int temp = arr[i];
arr[i] = arr[i - step];
arr[i - step] = temp;
}
}
step = step / 2;
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+",");
}
System.out.println();
}

return arr;
}

归并排序

基本思想:将待排序序列R[0…n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。
归并排序其实要做两件事:
(1)“分解”——将序列每次折半划分。
(2)“合并”——将划分后的序列段两两合并后排序。

核心代码:

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
29
30
31
32
33
34
35
36
37
public static int[] sort(int[] nums, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
sort(nums, low, mid);// 左边
sort(nums, mid + 1, high);// 右边
merge(nums, low, mid, high);// 左右归并
}
return nums;
}
public static void merge(int[] nums, int low, int mid, int high) {
int[] temp = new int[high - low + 1];
int i = low;// 左指针
int j = mid + 1;// 右指针
int k = 0;
// 把较小的数先移到新数组中
while (i <= mid && j <= high) {
if (nums[i] < nums[j]) {
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
}
}
// 把左边剩余的数移入数组
while (i <= mid) {
temp[k++] = nums[i++];
}
// 把右边边剩余的数移入数组
while (j <= high) {
temp[k++] = nums[j++];
}
// 把新数组中的数覆盖nums数组
for (int k2 = 0; k2 < temp.length; k2++) {
nums[k2 + low] = temp[k2];
}
}

}

快速排序

基本思想:快速排序采用的思想是分治思想。
快速排序是找出一个元素(理论上可以随便找一个)作为基准,然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。

核心代码:

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
29
30
31
32
33
/**
* 快速排序
*
* @author sgl
*
*/
public class QuickSort {
static void quicksort(int n[], int left, int right) {
int dp;
if (left < right) {
dp = partition(n, left, right);
quicksort(n, left, dp - 1);
quicksort(n, dp + 1, right);
}
}

static int partition(int n[], int left, int right) {
int pivot = n[left];
while (left < right) {
while (left < right && n[right] >= pivot)
right--;
if (left < right)
n[left++] = n[right];
while (left < right && n[left] <= pivot)
left++;
if (left < right)
n[right--] = n[left];
}
n[left] = pivot;
return left;
}

}

原文作者:GuoLei Song

原文链接:http://www.glmapper.com/2018/11/10/alg-one/

发表日期:November 10th 2018, 1:49:17 pm

更新日期:November 10th 2018, 1:50:06 pm

版权声明:转载请注明出处

CATALOG
  1. 1. 插入排序
  2. 2. 选择排序
  3. 3. 冒泡排序
  4. 4. 希尔排序
  5. 5. 归并排序
  6. 6. 快速排序