原地歸並排序


不需要輔助數組即可歸並。

關鍵在於merge這個函數。兩段遞增的子數組arr[begin…mid-1]和arr[mid…end],i=begin,j=mid,k=end

image

 

i往后移動,找到第一個arr[i]>arr[j]的索引

image

j往后移動,再找第一個arr[j]>arr[i]的索引

image

然后我們將i到mid的部分和mid到j-1的部分對調,較小的部分就調到前面去了,然后從后面的部分與j到k的部分又是兩個遞增的子數組,繼續迭代即可。

#include <iostream>
using namespace std;

//交換兩個數
void swap(int *a,int *b)
{
	int temp=*a;
	*a=*b;
	*b=temp;
}

//將長度為n的數組逆序
void reverse(int *arr,int n)
{
	int i=0,j=n-1;
	while(i<j)
	{
		swap(arr[i],arr[j]);
		i++;
		j--;
	}
}

//將數組向左循環移位i個位置
void exchange(int *arr,int n,int i)
{
	reverse(arr,i);
	reverse(arr+i,n-i);
	reverse(arr,n);
}

//數組兩個有序部分的歸並
void merge(int *arr,int begin,int mid,int end)
{
	int i=begin,j=mid,k=end;
	while(i<j && j<=k)
	{
		int step=0;
		while(i<j && arr[i]<=arr[j])
			++i;
		while(j<=k && arr[j]<=arr[i])
		{
			++j;
			++step;
		}
		exchange(arr+i,j-i,j-i-step);
		i=i+step;
	}
}

void MergeSort(int *arr,int l,int r)
{
	if(l<r)
	{
		int mid=(l+r)/2;
		MergeSort(arr,l,mid);
		MergeSort(arr,mid+1,r);
		merge(arr,l,mid+1,r);
	}
}

int main()
{
	int arr[]={6,4,3,1,7,8,2,9,5,0};
	int len=sizeof(arr)/sizeof(arr[0]);
	MergeSort(arr,0,len-1);
	for(int i=0;i<len;++i)
		cout <<arr[i]<<" ";
	cout <<endl;
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM