1.具体原理就不过多介绍了,先把C++程序设计上面的代码放上来
#include <iostream>
using namespace std;
void arraycopy(int source[], int sourceStartIndex, int target[], int targetStartIndex, int length);
void merge(int list1[], int list1Length, int list2[], int list2Length, int temp[]);
void mergeSort(int list[], int arraySize)
{
if (arraySize > 1)
{
int* firstHalf = new int[arraySize / 2];
arraycopy(list, 0, firstHalf, 0, arraySize/2);
mergeSort(firstHalf, arraySize/2);
int secondHalfLength = arraySize - arraySize/2;
int* secondHalf = new int[secondHalfLength];
arraycopy(list, arraySize/2, secondHalf, 0, secondHalfLength);
mergeSort(secondHalf, secondHalfLength);
int* temp = new int[arraySize];
merge(firstHalf, arraySize/2, secondHalf, secondHalfLength, temp);
arraycopy(temp, 0, list, 0, arraySize);
delete[]temp;
delete[]secondHalf;
delete[]firstHalf;
}
}
void arraycopy(int source[], int sourceStartIndex, int target[], int targetStartIndex, int length)
{
for (int i = 0; i < length; i++)
{
target[targetStartIndex++] = source[sourceStartIndex++];
}
}
void merge(int list1[], int list1Length, int list2[], int list2Length, int temp[])
{
int i = 0, j = 0, k = 0;
while (i < list1Length && j < list2Length)
{
if (list1[i] < list2[j])
{
temp[k++] = list1[i++];
}
else
{
temp[k++] = list2[j++];
}
}
while (i < list1Length)
{
temp[k++] = list1[i++];
}
while (j < list2Length)
{
temp[k++] = list2[j++];
}
}
int main()
{
int p[] = {9, 6, 4, 5, 2, 3, 1, 7, 8, 0};
int len = 10;
mergeSort(p, len);
for (int i = 0; i < len; i++)
{
cout<<p[i]<<" ";
}
}
分析:这种情况下,个人觉得空间复杂度会比较大每一层都要使用new,总共logN层,空间复杂度应为O(NlogN)。
2.放上来一种设定全局变量的方法,从而使得空间复杂度为O(N)
#include <iostream>
using namespace std;
int s1[10] = {9, 6, 4, 5, 2, 3, 1, 7, 8, 0};
int s2[10]; //原数组为s1,临时数组为s2。
void merge(int low, int mid, int high);
void mergeSort(int firstIndex, int secondIndex)
{
if (firstIndex < secondIndex)
{
int mid = (firstIndex+secondIndex)/2;
mergeSort(firstIndex, mid);
mergeSort(mid+1, secondIndex);
merge(firstIndex, mid, secondIndex);
}
}
void merge(int low, int mid, int high)
{
int i = low, j = mid+1, k = low;
while(i <= mid && j <= high)
{
if (s1[i] < s1[j])
{
s2[k++] = s1[i++];
}
else
{
s2[k++] = s1[j++];
}
}
while (i <= mid)
{
s2[k++] = s1[i++];
}
while (j <= high)
{
s2[k++] = s1[j++];
}
for (int l = low; l <= high; l++)
{
s1[l] = s2[l]; //这个for循环不能忘,因为s2会被不断地冲洗掉!
}
}
int main()
{
mergeSort(0, 9);
for (int i = 0; i < 10; i++)
{
cout<<s2[i]<<" ";
}
}
3.O(1)空间合并算法
问题描述:设子数组:a[0:k-1]和a[k:n-1]已排好顺序(0 <=k<=n-1)。试设计一个合并这2个子数组为排好序的数组a[0:n-1]的算法。要求算法在最坏情况下所用的计算时间为O(n),且只用到O(1)的辅助空间。
我们用循环换位合并算法:
图中红色部分为每一步需要向左循环的数组范围,其实就是讲上面的一排数插入到下面中。
#include <iostream>
using namespace std;
int binarySearch(int list[], int key, int low, int high)
{
int mid;
while(low <= high)
{
mid = (low + high)/2;
if (key == list[mid])
return mid;
else if(key > list[mid])
low = mid + 1;
else
high = mid - 1;
}
if (key > list[mid])
{
return mid+1;
}
else
return mid;
}
void leftShift(int list[], int low, int high)
{
int temp = list[low];
for (int i = low; i < high; i++)
{
list[i] = list[i+1];
}
list[high] = temp;
}
void merge(int list[], int k, int len)
{
int firstLow = 0;
int secondLow = k, secondHigh = len-1;
while (firstLow < secondLow)
{
int pos = binarySearch(list, list[firstLow], secondLow, secondHigh);
leftShift(list, firstLow, pos-1);
secondLow--;
}
}
int main()
{
int list[] = {1, 3, 5, 7, 2, 4, 6, 8};
int k = 4, len = 8;
merge(list, k, len);
for (int i = 0; i < len; i++)
{
cout<<list[i]<<" ";
}
}