归并排序

归并排序算法

个人理解

分治算法,虽然目前还不太理解,不过味道大概嗅到了一些

先一半一半的分开,然后到了 最小的不可分割的原子层面,进行比较,按顺序交换,这样就达到了最小分组层面的有序

然后往上回溯,回溯的时候呢,往上找,两个最小分组进行排序,只不过因为原本的数组已经有序了,我们可以放心的从左往右遍历。因此我们新开辟一份空间,搞一个数组,依次从左往右遍历两个最小分组,谁小复制谁即可。复制完成以后再重新拷贝回原本的数组空间即可。

分治

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
很多采用的是递归的方法进行的实现,但是这样有个缺点在于,当数据很大的时候栈会溢出

看到《大话数据结构》的一些讲解,讲到可以利用非递归方式进行实现

具体的实现思路是

整体类似插入排序

既然我们总是要找到最小的单位进行比较,不如直接从最小的单位开始了。反过来进行实现。(个人认为递归只是在数据大小不能提前确定的情况下采用,然而我们每次进行排序的序列都是可以提前知道数据量大小的,因此这类问题都可以进行逆向,采用非递归的方法进行实现)

那直接从最小的两个的进行比较,先两个进行插入排序,然后两个都是有序数列以后,再进行两个包含两个元素的有序数列的插入排序。然后再次扩展为两个包含四个元素的有序数列的插入排序。

总体思路

2个2个排序,完成后是 有序 2 2 2 2…孤儿
4个4个排序,完成后是 有序 4 4 4 4…孤儿
8个8个排序,完成后是 有序 8 8 8 8…孤儿

对于孤儿序列的处理方法,是和最后一个序列一起进行有序插入排序

代码写之

package sort;

import java.util.Arrays;

public class MergetSort
{

	public static void main(String[] args)
	{

		int[] arr =
		{ 9, 8, 7, 6, 5, 4, 3, 2, 1, 6 ,5,6,7,2,5,74,65,4,5,4,2,6};
		System.out.println(Arrays.toString(arr));
		System.out.println("---------------开始排序---------------");
		MergeSort(arr);

	}

	/**
	 * 
	 * @param arr         要插入排序的数组
	 * @param temp        临时存放的数组,用于整体赋值
	 * @param GroupLength 排序需要的数组长度
	 */

	public static void MergeSort(int[] arr)
	{
		int[] temp = new int[arr.length];
		int GroupSize = 1;
		int GroupNum = 0;
		int left, right, mid;
		while (GroupSize*2 < arr.length)
		{
			System.out.println("----------------"+GroupSize+"个一组"+"-------------------");
			GroupNum = arr.length / GroupSize;
			for (int i = 0; (i + 1) < GroupNum; i += 2)
			{
				left = i * GroupSize;
				right = (i + 2) * GroupSize - 1;
				mid = (left + right) / 2;
				Merge(arr, temp, left, mid, right); // 当前分组和下一个分组进行合并
				System.out.println(Arrays.toString(arr));
			}
			//最后还有个孤儿组,和最后一个组搞一搞
			//8 3  0-7  3 5
			left = (GroupNum-1)*GroupSize;//最后一个组的第一个
			right = arr.length-1;//最后一个
			mid = GroupNum*GroupSize-1;//最后一个组的最后一个
			Merge(arr, temp, left, mid, right); // 当前分组和下一个分组进行合并
			
			GroupSize *= 2; // 组的大小翻一番
		}
		//对最后一组进行处理
		mid = GroupNum*GroupSize/2-1;
		Merge(arr, temp, 0, mid, arr.length-1); // 当前分组和下一个分组进行合并
		System.out.println("---------------最后一次---------------");
		System.out.println(Arrays.toString(arr));

	}

	// 合并一个序列的两个有序数列,
	//由于放进来的不是整个序列,因此需要指定序号

	public static void Merge(int[] arr, int temp[], int left, int mid, int right)
	{

		int i = left;
		int j = mid + 1;
		int k = left;
		while (i <= mid && j <= right)
		{
			if (arr[i] < arr[j])
			{
				temp[k++] = arr[i++];
			} else
			{
				temp[k++] = arr[j++];
			}

		}

		while (i <= mid)
		{
			temp[k++] = arr[i++];
		}
		while (j <= right)
		{
			temp[k++] = arr[j++];
		}
		// 复制回arr数组
		for (int k2 = left; k2 <= right; k2++)
		{
			arr[k2] = temp[k2];
		}

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值