归并排序

归并排序:将两个或两个以上的有序子序列归并为一个有序序列。基于分治思想。

  • 时间复杂度=O(nlog2n),空间复杂度=O(n)。稳定排序

归并排序

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 internal class Program
{
private static void Main(string[] args)
{
int[] arr = { 5, 7, 3, 8, 6, 9, 4, 2 };
Console.WriteLine("未排序前的数组:");
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i] + " ");
}
Console.WriteLine();
merge_sort(arr, 1, 8);
Console.WriteLine("排序后的数组:");
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i] + " ");
}
}

// 分割数组
private static void merge_sort(int[] arr,int start,int end)
{
if(arr == null || start >= end)
{
return;
}
int mid = (start + end) / 2; // 取得数组中间值下标
// 继续分割
merge_sort(arr,start,mid);
merge_sort(arr,mid + 1,end);
merge(arr,start,mid,end);
}

privatr static void merge(int[] arr,int start,int mid,int end)// 1 1 2
{
int left = mid - start + 1; // 获得左边数组元素个数
int right = end - mid; // 获得右边数组元素个数
int leftArr = new int[left + 1];
int rightArr = new int[right + 1];
int i;
for(i = 0; i < left; i++)
{
leftArr[i] = arr[start - 1 + i];
}
leftArr[i] = 2147483647; // 把数组最后一个元素设置为最大值
for(i = 0; i < right; i++)
{
rightArr[i] = arr[mid + i];
}
leftArr[i] = 2147483647; // 把数组最后一个元素设置为最大值
int j = 0;
i = 0;
for(int k = start; k < end; k++)
{
if(leftArr[i] <= rightArr[j])
{
arr[k - 1] = leftArr[i];
i++;
}
else
{
arr[k - 1] = rightArr[j];
j++;
}
}
}
}

输出:

未排序前的数组:
5 7 3 8 6 9 4 2
排序后的数组:
2 3 4 5 6 7 8 9


计数排序

计数排序:通过统计序列中各个元素出现的次数,完成对整个序列的升序或降序排序。(元素之间最好是在0~9之间的数值差)

  • 时间复杂度=O(n+k),空间复杂度=O(n+k)。稳定排序

计数排序

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
internal class Program
{
private static void Main(string[] args)
{
int[] arr = { 2, 4, 1, 2, 5, 3, 4, 8, 7 };
Console.WriteLine("未排序前的数组:");
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i] + " ");
}
Console.WriteLine();
countingSort(arr);
Console.WriteLine("排序后的数组:");
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i] + " ");
}
}

private static int get_max(int[] arr)
{
int max = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}

private static void countingSort(int[] arr)
{
int length = arr.Length;
// 找出数组中的最大值
int max = get_max(arr);
int[] array = new int[max + 1]; // 创建一个统计元素出现次数的数组
int[] output = new int[length]; // 排序数组
// 统计元素出现个数,存储在对应的位置上
for (int i = 0; i < length; i++)
{
array[arr[i]]++;
}
// 累加出现的次数
for (int i = 1; i < max + 1; i++)
{
array[i] += array[i - 1];
}
// 根据次数进行排序
for (int i = 0; i < length; i++)
{
output[array[arr[i]] - 1] = arr[i];
array[arr[i]]--;
}
// 复制到arr数组中 2, 4, 1, 2, 5, 3, 4, 8, 7
for (int i = 0; i < length; i++)
{
arr[i] = output[i];
}
}
}

输出:

未排序前的数组:
2 4 1 2 5 3 4 8 7
排序后的数组:
1 2 2 3 4 4 5 7 8


基数排序

基数排序:数字逐位比较。

  • 时间复杂度=O(n×m),空间复杂度=O(n×m)。稳定排序。n:数据个数,m:数据位数。

基数排序

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
internal class Program
{
private static void Main(string[] args)
{
int[] arr = { 121, 432, 564, 23, 1, 45, 788 };
Console.WriteLine("未排序前的数组:");
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i] + " ");
}
Console.WriteLine();
radixSort(arr);
Console.WriteLine("排序后的数组:");
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i] + " ");
}
}

private static int getMax(int[] arr)
{
int max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}

private static void countingSort(int[] arr, int place)
{
int length = arr.Length;
int[] output = new int[length];

int max = (arr[0] / place) % 10;
for (int i = 1; i < length; i++)
{
if (((arr[i] / place) % 10) > max)
{
max = (arr[i] / place) % 10;
}
}

int[] count = new int[max + 1];
for (int i = 0; i < length; i++)
{
count[(arr[i] / place) % 10]++;
}

for (int i = 1; i < max + 1; i++)
{
count[i] += count[i - 1];
}

// 一定要从后往前排
for (int i = length - 1; i >= 0; i--)
{
output[count[(arr[i] / place) % 10] - 1] = arr[i];
count[(arr[i] / place) % 10]--;
}

for (int i = 0; i < length; i++)
{
arr[i] = output[i];
}
}

private static void radixSort(int[] arr)
{
int max = getMax(arr);
// 根据最高位数,从低位依次进行计数排序
for (int i = 1; max / i > 0; i *= 10)
{
countingSort(arr, i);
}
}
}

输出:

未排序前的数组:
121 432 564 23 1 45 788
排序后的数组:
1 23 45 121 432 564 788


桶/箱排序

桶/箱排序:待排序数组,分配到若干个桶,各自执行排序任务。是一种基于分治思想、效率很高的排序算法。(适用于数据范围较小且分布均匀的浮点数数据)

  • 时间复杂度=O(n+m+n(logn-logm)),空间复杂度=O(n+m)。稳定排序。n:数据个数,m:数据位数。

桶排序