65,189
社区成员




/*
数组a[begin, mid] 和 a[mid+1, end]是各自有序的,对两个子段进行Merge得到a[begin , end]的有序数组。 要求空间复杂度为O(1)
方案:
1、两个有序段位A和B,A在前,B紧接在A后面,找到A的第一个大于B[0]的数A[i], A[0...i-1]相当于merge后的有效段,在B中找到第一个大于A[i]的数B[j],
对数组A[i...j-1]循环右移j-k位,使A[i...j-1]数组的前面部分有序
2、如此循环merge
3、循环右移通过先子段反转再整体反转的方式进行,复杂度是O(L), L是需要循环移动的子段的长度
*/
#include<iostream>
using namespace std;
void Reverse(int *a , int begin , int end ) //反转
{
for(; begin < end; begin++ , end--)
swap(a[begin] , a[end]);
}
void RotateRight(int *a , int begin , int end , int k) //循环右移
{
int len = end - begin + 1; //数组的长度
k %= len;
Reverse(a , begin , end - k);
Reverse(a , end - k + 1 , end);
Reverse(a , begin , end);
}
// 将有序数组a[begin...mid] 和 a[mid+1...end] 进行归并排序
void Merge(int *a , int begin , int end )
{
int i , j , k;
i = begin;
j = 1 + ((begin + end)>>1); //位运算的优先级比较低,外面需要加一个括号,刚开始忘记添加括号,导致错了很多次
while(i <= end && j <= end && i<j)
{
while(i <= end && a[i] < a[j])
i++;
k = j; //暂时保存指针j的位置
while(j <= end && a[j] < a[i])
j++;
if(j > k)
RotateRight(a , i , j-1 , j-k); //数组a[i...j-1]循环右移j-k次
i += (j-k+1); //第一个指针往后移动,因为循环右移后,数组a[i....i+j-k]是有序的
}
}
void MergeSort(int *a , int begin , int end )
{
if(begin == end)
return ;
int mid = (begin + end)>>1;
MergeSort(a , begin , mid); //递归地将a[begin...mid] 归并为有序的数组
MergeSort(a , mid+1 , end); //递归地将a[mid+1...end] 归并为有序的数组
Merge(a , begin , end); //将有序数组a[begin...mid] 和 a[mid+1...end] 进行归并排序
}
int main(void)
{
int n , i , a[20];
while(cin>>n)
{
for(i = 0 ; i < n ; ++i)
cin>>a[i];
MergeSort(a , 0 , n - 1);
for(i = 0 ; i < n ; ++i)
cout<<a[i]<<" ";
cout<<endl;
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int lower_bound(int *arr, int begin, int end, int target) {
while (begin <= end) {
int middle = begin + (end - begin) / 2;
if (target <= arr[middle]) {
end = middle - 1;
} else {
begin = middle + 1;
}
}
return end + 1;
}
int merge(int *arr, int num) {
if (arr == NULL) {
return -1;
}
if (num <= 1) {
return 0;
}
int l_begin = 0, l_end = (num / 2) - 1;
int r_begin = l_end + 1, r_end = num -1;
while (l_begin <= l_end) {
if (arr[l_begin] > arr[r_begin]) {
int temp = arr[l_begin];
arr[l_begin] = arr[r_begin];
/* 慢速版
int ndx = r_begin + 1;
while (ndx <= r_end && temp > arr[ndx]) {
arr[ndx - 1] = arr[ndx];
++ ndx;
}
arr[ndx - 1] = temp;
*/
/* 二分版 */
if (r_end - r_begin + 1 > 1) {
int ndx = lower_bound(arr, r_begin + 1, num - 1, temp);
if (ndx == r_begin + 1) {
arr[r_begin] = temp;
} else {
memmove(arr + r_begin, arr + r_begin + 1,
sizeof(int) * (ndx - r_begin - 1));
arr[ndx - 1] = temp;
}
} else {
arr[r_begin] = temp;
}
}
++ l_begin;
}
return 0;
}
int main(int argc, char* const argv[]) {
int arr[] = {1, 4, 4, 5, 6, 6, 1, 2, 2, 3, 3, 4, 5};
int ret = merge(arr, sizeof(arr) / sizeof(arr[0]));
if (!ret) {
int i = 0;
for ( ; i < sizeof(arr) / sizeof(arr[0]); ++ i ) {
printf("%d ", arr[i]);
}
printf("\n");
}
return 0;
}
void mergeArray(int a[], int first, int mid ,int last)
{
int i, j = mid +1;
int k, flag = 0;
while ( a[j] < a[j-1] && j <= last )
{
k = flag;
for ( i = j-1; i >= k ; i--)
if ( a[i] > a[i+1] )
{
Swap( a[i], a[i+1] );
flag = i;
}
j ++;
}
}