归并排序
原理
先将序列两两分组,把序列归并为$$\lceil\frac{n}{2}\rceil$$个组,组内单独排序;然后将这些组两两归并,生成$$\lceil\frac{n}{4}\rceil$$个组,组内再单独排序;以此类推,直到只剩下一个组为止。
归并排序的时间复杂度为O(nlogn)
。
递归实现
void mergeArray(int A[], int lo, int mid, int hi)
{
int* temp = new int[hi - lo + 1];
int i = lo, j = mid + 1;
int k = 0;
while (i <= mid && j <= hi)
{
if (A[i] <= A[j])
temp[k ++] = A[i ++];
else
temp[k ++] = A[j ++];
}
while ( i <= mid) temp[k ++] = A[i ++];
while ( j <= hi) temp[k ++] = A[j ++];
for (int i = lo, k = 0; i <= hi; i ++, k ++)
A[i] = temp[k];
delete[] temp;
}
void mergeSort(int A[], int lo, int hi)
{
if (lo >= hi) return;
int mid = lo + hi >> 1;
mergeSort(A, lo, mid);
mergeSort(A, mid + 1, hi);
//mergeArray(A, lo, mid, hi);
sort (A, A + (hi - lo + 1));
}
非递归实现
void mergeArray(int A[], int lo, int mid, int hi)
{
int* temp = new int[hi - lo + 1];
int i = lo, j = mid + 1;
int k = 0;
while (i <= mid && j <= hi)
{
if (A[i] <= A[j])
temp[k ++] = A[i ++];
else
temp[k ++] = A[j ++];
}
while ( i <= mid) temp[k ++] = A[i ++];
while ( j <= hi) temp[k ++] = A[j ++];
for (int i = lo, k = 0; i <= hi; i ++, k ++)
A[i] = temp[k];
delete[] temp;
}
void mergeSort(int A[]) // step 组内元素的个数,step / 2为左子区间元素的个数
{
for (int step = 2; step / 2 < n; step *= 2) //每 step 个元素元素一组,组内前 step / 2 和后 step / 2 个元素进行合并
{
for (int i = 0; i < n; i +=step) //对每一组进行操作
{
int mid = i + step / 2 - 1; //左子区间的元素个数为 step / 2 个
if (mid + 1 < n) //右子区间存在元素则合并
{
mergeArray(A, i, mid, min(i + step - 1, n - 1));
}
}
}
}
// 使用sort 函数替代 mergeArray 函数
void mergeSort(int A[])
{
for (int step = 2; step / 2 <= n; step *= 2)
{
for (int i = 0; i < n; i ++)
sort(A + i, A + min(i + step, n ));
}
}
//如果下标从0开始
void mergeSort1(int a[])
{
for (int step = 2; step / 2 <= n; step *= 2)
{
for (int i = 0; i < n; i += step)
{
int mid = i + step / 2 - 1;
if (mid + 1 < n)
{
merge(a, i , mid, min(n - 1, i + step - 1));
}
}
}
//如果时间允许,使用sort函数替代merge函数
void mergeSort1(int A[])
{
for (int step = 2; step / 2 <= n; step *= 2)
{
for (int i = 0; i < n; i++)
{
sort(A + i, A + min(i + step, n + 1));
}
}
}
快速排序
快速排序时间复杂度O(nlogn)
。
关于随机数
1.所需头文件
#include <stdlib.h>
#include <time.h>
2.举例
-
rand()
函数只能生成[0, RAND_MAX]
范围内的整数。 -
RAND_MAX
是stdlib.h
种的一个常数,不同系统环境,该值不同,一般为32767
。 - 输入给定范围
[a, b]
内的随机数,使用rand() % (b - a + 1) + a
。 -
mian()
函数开头加上srand((unsigned)time(NULL));
。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand((unsigned)time(NULL));
for (int i \= 0; i < 10; i ++)
printf("%d ", rand() % (5 \- 1 + 1) + 1);
return 0;
}
实现
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <iostream>
using namespace std;
int partition(int A[], int left, int right)
{
//在[left, right]内生成随机数
int p = (round(1.0 *rand() / RAND_MAX * (right - left) + left));
// int p = rand() % (right - left + 1) + left;
swap(A[p], A[left]);
int temp = A[left];
while (left < right)
{
while (left < right && A[right] > temp) right --;
A[left] = A[right];
while (left < right && A[left] <= temp) left ++;
A[right] = A[left];
}
A[left] = temp;
return left; //返回相遇的下标
}
void quickSort(int A[], int left, int right)
{
if (left < right)
{
int pos = partition(A, left, right);
quickSort(A, left, pos - 1);
quickSort(A, pos + 1, right);
}
}
int main()
{
srand((unsigned)time(NULL));
int A[] = {3, 10, 4, 2, 23, 15};
int n = sizeof(A) / sizeof(int);
quickSort(A, 0, n - 1);
for (int x : A)
{
printf("%d ", x);
}
return 0;
}
参考《算法笔记》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。