归并排序
归并排序是一种分治算法,它将待排序的序列不断地分割成两个子序列,直到每个子序列只有一个元素,然后将这些子序列合并成一个有序序列。
下面分别介绍归并排序的递归和非递归算法。
递归算法:
- 将待排序的序列平均分割成两半。
- 对左半部分和右半部分分别进行递归调用归并排序。
- 对左右两个有序序列进行合并,得到完整的有序序列。
递归算法的实现比较简单,代码如下:
public static void mergeSort(int[] arr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
public static void merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int i = left;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= right) {
if (arr[i] < arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
while (i <= mid) {
temp[k++] = arr[i++];
}
while (j <= right) {
temp[k++] = arr[j++];
}
for (int m = 0; m < temp.length; m++) {
arr[left + m] = temp[m];
}
}
非递归算法:
- 将待排序的序列按照一定的大小划分成若干个子序列。
- 对每个子序列进行插入排序,使得每个子序列都有序。
- 将相邻的两个子序列合并,得到一个更大的有序序列。
- 重复步骤3,直到所有子序列都被合并成一个有序序列。
非递归算法需要使用一个辅助数组,代码如下:
public static void mergeSort(int[] arr) {
int len = arr.length;
int[] temp = new int[len];
for (int size = 1; size < len; size += size) {
for (int left = 0; left < len - size; left += size + size) {
int mid = left + size - 1;
int right = Math.min(left + size + size - 1, len - 1);
merge(arr, temp, left, mid, right);
}
}
}
public static void merge(int[] arr, int[] temp, int left, int mid, int right) {
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right) {
if (arr[i] < arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
while (i <= mid) {
temp[k++] = arr[i++];
}
while (j <= right) {
temp[k++] = arr[j++];
}
for (int m = left; m <= right; m++) {
arr[m] = temp[m];
}
}
该代码实现了归并排序的非递归算法,首先将输入数组按照一定的大小划分成若干个子序列,然后对每个子序列进行插入排序,接着将相邻的两个有序子序列合并,得到一个更大的有序序列。重复这个过程,直到所有子序列都被合并成一个有序序列。
以下是C++中使用递归实现归并排序的代码示例:
#include <iostream>
using namespace std;
void merge(int arr[], int left, int mid, int right)
{
int i, j, k;
int n1 = mid - left + 1;
int n2 = right - mid;
int LeftArr[n1], RightArr[n2];
for (i = 0; i < n1; i++)
LeftArr[i] = arr[left + i];
for (j = 0; j < n2; j++)
RightArr[j] = arr[mid + 1 + j];
i = 0;
j = 0;
k = left;
while (i < n1 && j < n2) {
if (LeftArr[i] <= RightArr[j]) {
arr[k] = LeftArr[i];
i++;
}
else {
arr[k] = RightArr[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = LeftArr[i];
i++;
k++;
}
while (j < n2) {
arr[k] = RightArr[j];
j++;
k++;
}
}
void mergeSort(int arr[], int left, int right)
{
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
int main()
{
int arr[] = { 12, 11, 13, 5, 6, 7 };
int arr_size = sizeof(arr) / sizeof(arr[0]);
cout << "Given array is \n";
for (int i = 0; i < arr_size; i++)
cout << arr[i] << " ";
mergeSort(arr, 0, arr_size - 1);
cout << "\nSorted array is \n";
for (int i = 0; i < arr_size; i++)
cout << arr[i] << " ";
return 0;
}
在这个代码中,merge()
函数被用来合并两个有序数组。mergeSort()
函数则是递归调用了自己,每次把给定数组分成两半,然后再进行归并排序。最终得到一个排序好的数组。
以下是 C++ 实现非递归排序的归并排序的代码示例:
#include <iostream>
using namespace std;
void merge(int arr[], int l, int m, int r) {
int n1 = m - l + 1;
int n2 = r - m;
int L[n1], R[n2];
for (int i = 0; i < n1; i++)
L[i] = arr[l + i];
for (int j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
}
else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int n) {
for (int curr_size = 1; curr_size <= n - 1; curr_size = 2 * curr_size) {
for (int left_start = 0; left_start < n - 1; left_start += 2 * curr_size) {
int mid = min(left_start + curr_size - 1, n - 1);
int right_end = min(left_start + 2 * curr_size - 1, n - 1);
merge(arr, left_start, mid, right_end);
}
}
}
void printArray(int A[], int size) {
for (int i = 0; i < size; i++)
cout << A[i] << " ";
}
// 测试代码
int main() {
int arr[] = { 12, 11, 13, 5, 6, 7 };
int arr_size = sizeof(arr) / sizeof(arr[0]);
cout << "给定数组为" << endl;
printArray(arr, arr_size);
mergeSort(arr, arr_size);
cout << "\n排序后的数组为" << endl;
printArray(arr, arr_size);
return 0;
}
在这个实现中,merge() 函数用于将两个有序数组合并。mergeSort() 函数使用非递归方式对整个数组进行归并排序。
主函数中给定了一个测试数组,并输出排序前和排序后的数组。
计数排序
计数排序是一种非比较排序算法,它的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数,然后将x直接放在输出序列的第n个位置上(n为小于x的元素的个数加上等于x的元素的个数),从而实现了序列的排序。
下面是Java语言的计数排序代码实现:
public static void countingSort(int[] arr) {
int len = arr.length;
if (len < 2) {
return;
}
// 计算最大值和最小值
int max = arr[0];
int min = arr[0];
for (int i = 1; i < len; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
}
// 计算计数数组
int range = max - min + 1;
int[] count = new int[range];
for (int i = 0; i < len; i++) {
count[arr[i] - min]++;
}
// 累加计数数组
for (int i = 1; i < range; i++) {
count[i] += count[i - 1];
}
// 排序到输出数组
int[] output = new int[len];
for (int i = len - 1; i >= 0; i--) {
output[--count[arr[i] - min]] = arr[i];
}
// 复制到原数组
for (int i = 0; i < len; i++) {
arr[i] = output[i];
}
}
该代码实现了计数排序算法,首先计算输入数组的最大值和最小值,然后初始化一个计数数组count,遍历输入数组并将每个元素出现的次数记录在count中,接着将count数组累加,计算出小于等于某个元素的元素个数,最后根据count数组将元素输出到输出数组中。
计数排序是一种非比较排序算法,可以对于一定范围内的整数排序,时间复杂度为O(n+k),其中n为要排序的元素个数,k为整数的范围。
好的,以下是C++实现计数排序的示例代码:
#include <iostream>
using namespace std;
const int MAX_VALUE = 10000; // 假设数组中的元素最大值为10000
void countingSort(int arr[], int n)
{
int count[MAX_VALUE + 1] = {0}; // 初始化一个计数数组
for (int i = 0; i < n; ++i)
{
++count[arr[i]]; // 将arr[i]出现的次数计入计数数组
}
int index = 0;
for (int i = 0; i <= MAX_VALUE; ++i)
{
for (int j = 0; j < count[i]; ++j)
{
arr[index++] = i; // 按计数数组顺序重构原始数组
}
}
}
int main()
{
int arr[] = {3, 1, 4, 7, 2, 8, 5, 6};
int n = sizeof(arr) / sizeof(arr[0]);
countingSort(arr, n);
for (int i = 0; i < n; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
该代码中,我们首先定义了一个常量MAX_VALUE
,这个常量用于表示数组中元素的最大值。然后,我们定义了一个计数数组count
,并初始化为0。
接下来,我们遍历原始数组arr
,将每个元素出现的次数计入计数数组count
中。然后,我们按计数数组count
的顺序重构原始数组arr
。
最后,我们通过循环遍历重构后的数组arr
,将其输出到控制台。
计数排序是一种非比较排序算法,可以对于一定范围内的整数排序,时间复杂度为O(n+k),其中n为要排序的元素个数,k为整数的范围。
以下是Python实现计数排序的代码:
def count_sort(arr):
n = len(arr)
# 确定数组中最大值
max_val = max(arr)
# 计数数组
count = [0] * (max_val + 1)
# 存放排序结果的数组
output = [0] * n
# 统计每个元素出现的次数
for i in range(n):
count[arr[i]] += 1
# 累加count数组
for i in range(1, max_val + 1):
count[i] += count[i - 1]
# 将元素放入output数组中
for i in range(n - 1, -1, -1):
output[count[arr[i]] - 1] = arr[i]
count[arr[i]] -= 1
# 将结果复制回原始数组
for i in range(n):
arr[i] = output[i]
return arr
# 测试
arr = [4, 2, 10, 5, 3, 1, 9, 6, 8, 7]
print(count_sort(arr))
在该实现中,首先确定数组中的最大值max_val,然后创建一个count数组,用于统计每个数字出现的次数。接着遍历原始数组arr,在count[arr[i]]处加1,统计每个数字出现的次数。
之后遍历count数组,将其元素累加,这样count[i]的值就表示小于等于i的数字有多少个。接着从原始数组arr末尾开始向前遍历,将它的值放入output数组中,同时将count[arr[i]]的值减1,以便处理重复元素的情况。
最后再将output数组中的元素复制回原始数组arr,完成排序。