归并排序
时间复杂度: O(nlogn)
目录
版本一
版本二
版本一
void merge(int* arr, int lo, int mi, int hi)
{
int* A = arr + lo;//创建A数组
//创建B数组
int lb = mi - lo;
int* B = new int[lb];
//初始化B数组
for (int i = 0; i < lb;)
{
B[i] = A[i++];
}
//创建C数组,其实就是A数组,没有新开辟空间
int lc = hi - mi;
int* C = arr + mi;
//将BC数组中较小值填充到A
for (int i = 0, j = 0, k = 0; j < lb || k < lc;)
{
if (j < lb && (lc <= k || B[j] <= C[k]))//如果两个数相等, 把B数组的排在前面
{
A[i++] = B[j++];
}
if (k < lc && (lb <= j || C[k] < B[j]))
{
A[i++] = C[k++];
}
}
delete[] B;
}
void mergeSort(int* arr, int lo, int hi)
{
if (hi - lo < 2)
{
return;
}
int mi = (hi + lo) >> 1;
mergeSort(arr, lo, mi);
mergeSort(arr, mi, hi);
merge(arr, lo, mi, hi);
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
mergeSort(arr, 0, 10);
for (int i = 0; i < 10; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
运行结果:
正确性:
验证一:
当B覆盖A时,不会影响到C
验证二:
当B覆盖到A时,不会影响到C
当先将所有的B覆盖到A时,表面上C会全部覆盖剩下的空间,实际上A和C在内存中是一块空间,所以可以不用进行赋值操作,版本二进行了改进
验证四:
当先将所有的C覆盖到A时,然后将剩下的B依次覆盖剩下的空间
返回目录
版本二
改进: 由于验证三的缘故,可以改进
交换顺序原因: 当C全部填满A,k = lc,如果不交换顺序, B向A中填充一个元素,此时j++,如果j++此时等于lb,那么数组B就会越界访问,但是如果交换顺序就是先访问数组B,不会造成数组越界
void merge(int* arr, int lo, int mi, int hi)
{
int* A = arr + lo;//创建A数组
//创建B数组
int lb = mi - lo;
int* B = new int[lb];
//初始化B数组
for (int i = 0; i < lb;)
{
B[i] = A[i++];
}
//创建C数组,其实就是A数组,没有新开辟空间
int lc = hi - mi;
int* C = arr + mi;
//将BC数组中较小值填充到A
for (int i = 0, j = 0, k = 0; j < lb ;)
{
if (k < lc && (C[k] < B[j]))
{
A[i++] = C[k++];
}
if (lc <= k || B[j] <= C[k])//如果两个数相等, 把B数组的排在前面
{
A[i++] = B[j++];
}
}
delete[] B;
}
void mergeSort(int* arr, int lo, int hi)
{
if (hi - lo < 2)
{
return;
}
int mi = (hi + lo) >> 1;
mergeSort(arr, lo, mi);
mergeSort(arr, mi, hi);
merge(arr, lo, mi, hi);
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
mergeSort(arr, 0, 10);
for (int i = 0; i < 10; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
运行结果: