基本思想:先通過迭代將數組不斷進行二分,最後分成每組只有一個元素,在進行合併,合併是兩兩元素依次比較,放入臨時數組中。
1.首先應對數組進行分開,通過迭代的方法每次二分數組,直到每組只剩一個元素。mid=(start+end) /2。
2.對於上面左邊部分,進行歸併排序, 首先定義i,j兩個指針,分別進行比較,當a[i]<=a[j]時,將a[i]元素放入temp中,同時自增temp中的k和i指針。當a[i]>a[j]時,將a[j]元素放入temp中,同時自增temp中的k和j指針。
3.當j指針指向end時,a[j]<a[i],將a[j]元素放入temp中,同時自增temp中的k和j指針。此時j>end,跳出循環。
4.通過while循環將i中多餘的數據依次存放入temp中。最後將temp中輸入拷貝回數組a中
5.同理對於右半部分也是如此。
6.合併後仍然剩餘兩部分,再利用兩個指針重複上面過程進行i和j中的元素比較,將較小值拷貝至temp中,同時自增i或j指針,k指針。
代碼:
/*歸併排序:
將兩個已經排好序的數組進行合併即爲歸併
將待排序的數列分爲若干個長度爲1的子數列,然後將這些數列兩兩合併,得到
若干個長度爲2的有序數列,再將這些數列兩兩合併以此類推直到合併爲一個數列爲止*/
//將兩個有序數組合併爲一個有序數組,start:第一個的開始索引,mid:第一個結束索引,end:第二個結束索引
void Merge(int list[], int start, int mid, int end)
{
int *tmp = new int[end - start + 1];
int i = start, j = mid + 1, k = 0;
while (i <= mid && j <= end)
{
if (list[i] <= list[j])//移動兩個指針將比較後的元素放入輔助空間中
{
tmp[k++] = list[i++];
}
else
{
tmp[k++] = list[j++];
}
}
while (i <= mid)//j中已經沒有數據
{
tmp[k++] = list[i++];
}
while (j <= end)//i中沒有數據
{
tmp[k++] = list[j++];
}
for (i = 0; i < k; i++)
{
list[start + i] = tmp[i];
}
delete[] tmp;
}
//從上往下
void Merge_Sort_Up2down(int list[], int start, int end)
{
if (list == NULL || start >= end)
{
return;
}
int mid = (end + start) / 2;
Merge_Sort_Up2down(list, start, mid);//左半邊
Merge_Sort_Up2down(list, mid + 1, end);//右半邊
Merge(list, start, mid, end);
}
//從下往上
void MergeGroups(int list[], int len, int gap)
{
int i;
int twolen = 2 * gap;//兩個相鄰子數組長度
//每兩個相鄰子數組合並排序
for (i = 0; i + twolen - 1 < len; i += twolen)
{
Merge(list, i, i + gap - 1, i + twolen - 1);
}
if (i + gap - 1 < len - 1)//剩餘一個子數組沒有配對
{
Merge(list, i, i + gap - 1, len - 1);
}
}
void Merge_Sort_Down2up(int list[], int len)
{
int n;
if (list == NULL || len <= 0)
{
return;
}
for (n = 1; n < len; n++)
{
MergeGroups(list, len, n);
}
}
int main()
{
int list[] = { 12, 5, 4, 6, 7, 6, 1 };
Merge_Sort_Up2down(list, 0, sizeof(list) / sizeof(int)-1);
for (int i = 0; i < sizeof(list) / sizeof(int); i++)
{
cout << list[i] << endl;
}
}
歸併排序是一種穩定的排序方法,在最好、最壞、平均情況下的時間複雜度:,空間複雜度爲。