码迷,mamicode.com
首页 > 其他好文 > 详细

归并排序

时间:2014-07-20 22:35:13      阅读:283      评论:0      收藏:0      [点我收藏+]

标签:算法

归并排序是另一种运用分治法排序算法。与快速排序一样,它依赖于元素之间的比较来排序。但是,归并排序需要额外的存储空间来完成排序过程。

同样可以用分治法的思想将排序分为三个步骤。

  1. 分:将数据集等分为两半。
  2. 治:分别在两个部分用递归的方式继续使用归并排序法。
  3. 合:将分开的两个部分合并成一个有序的数据集。

归并排序与其他排序最大的不同在于,它的归并过程。这个过程就是将两个有序的数据集合并成一个有序的数据集。正如我们看到的,合并两个有序数据集的过程是高效的,因为我们只需要遍历一次即可。

归并排序本质上是将无序元素分割成许多个包含一个元素的集,然后不断地将这些小集合合并,直到一个新的大有序数据集生成。

bubuko.com,布布扣

根据上图实现DEBUG DEMO如下:

import java.util.Arrays;

/**
 * 归并排序
 * 
 * @author kevin LUAN
 * 
 */
public class GBSortDemo {
	public static void main(String[] args) {
		Integer[] arrays = new Integer[] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
		Integer[] dest = new Integer[arrays.length];
		mgSort(arrays, dest, 0, arrays.length);
		System.out.println("Sort result:"+Arrays.toString(dest));
	}

	private static void mgSort(Integer[] arr, Integer[] dest, int low, int high) {
		System.out.println(Arrays.toString(arr));
		int middle = getMiddle(low, high);
		if (high - low < 3) {
			copyData(arr, dest, low, high);
			return;
		}
		Integer[] left = new Integer[middle - low];
		if (left.length > 1) {
			System.arraycopy(arr, low, left, 0, left.length);
			mgSort(left, dest, 0, left.length);
		}
		Integer[] right = new Integer[high - middle];
		if (right.length > 0) {
			System.arraycopy(arr, middle, right, 0, right.length);
			mgSort(right, dest, 0, right.length);
		}
	}

	private static void sort(Integer[] left) {
		for (int i = 0; i < left.length; i++) {
			for (int j = i + 1; j < left.length; j++) {
				if (left[j] < left[i]) {
					left[j] = swap(left, i, left[j]);
				}
			}
		}
	}

	private static void copyData(Integer[] left, Integer[] dest, int low, int high) {
		sort(left);
		Integer start = 0;
		boolean isStart = false;
		for (int l = low; l < high; l++) {
			int val = left[l];
			for (int i = 0 + start; i < dest.length; i++) {
				if (dest[i] == null) {
					dest[i] = val;
					break;
				} else if (dest[i] > val) {
					if (isStart == false) {
						start = i;
					}
					val = swap(dest, i, val);
				}
			}
		}
	}

	private static int swap(Integer[] dest, int i, int val) {
		try {
			return dest[i];
		} finally {
			dest[i] = val;
		}
	}

	public static int getMiddle(int low, int high) {
		int total = high - low;
		if (total % 2 == 0) {
			return total / 2;
		} else {
			return total / 2 + 1;
		}
	}

}

运行Main函数:

[1, 3, 5, 7, 9, 2, 4, 6, 8, 0]

[1, 3, 5, 7, 9]

[1, 3, 5]

[1, 3]

[5]

[7, 9]

[2, 4, 6, 8, 0]

[2, 4, 6]

[2, 4]

[6]

[8, 0]

Sort result:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

进一步优化,去掉System.arraycopy()代码如下:


import java.util.Random;

/**
 * 归并排序
 * 
 * @author kevin
 * 
 */
public class GBSort {
	public static Integer[] randomArray(int total) {
		Random random = new Random();
		Integer[] arrays = new Integer[total];
		for (int i = 0; i < total; i++) {
			arrays[i] = random.nextInt(10);
		}
		return arrays;
	}

	public static void main(String[] args) {
		Integer[] arrays = randomArray(10000);
		long start = System.currentTimeMillis();
		arrays = sort(arrays);
		System.out.println("use time:" + (System.currentTimeMillis() - start));
	}

	private static Integer[] sort(Integer[] arr) {
		Integer[] dest = new Integer[arr.length];
		mgSort(arr, dest, 0, arr.length);
		return dest;
	}

	private static void mgSort(Integer[] arr, Integer[] dest, int low, int high) {
		int middle = getMiddle(low, high);
		if (high - low < 3) {
			copyData(arr, dest, low, high);
			return;
		}
		Integer left = middle - low;
		if (left > 1) {
			mgSort(arr, dest, low, low + left);
		}
		Integer right = high - middle;
		if (right > 0) {
			mgSort(arr, dest, middle, high);
		}
	}

	private static void sort(Integer[] left, int low, int high) {
		for (int i = low; i < high; i++) {
			for (int j = i + 1; j < high; j++) {
				if (left[j] < left[i]) {
					left[j] = swap(left, i, left[j]);
				}
			}
		}
	}

	/**
	 * 
	 * @param left
	 * @param dest
	 * @param low
	 *            低位下标
	 * @param high
	 *            高位+1
	 */
	private static void copyData(Integer[] src, Integer[] left, int low, int high) {
		if (high - low > 1) {
			sort(src, low, high);
		}
		int startIndex = 0;
		for (int l = low; l < high; l++) {
			int val = src[l];
			for (int i = startIndex = calAddIndex(left, startIndex, low, val); i < high; i++) {
				if (left[i] == null) {
					left[i] = val;
					break;
				} else if (left[i] > val) {
					val = swap(left, i, val);
				}
			}
		}
	}

	public static int calAddIndex(Integer ascArray[], int startIndex, int endIndex, Integer val) {
		int start = startIndex;
		int end = endIndex - 1;
		int oldStart = -1;
		int oldEnd = -1;
		if (end == 0) {
			return 0;
		}
		while (true) {
			if (start == oldStart && end == oldEnd || end - start <= 1) {
				return start;
			}
			oldEnd = end;
			oldStart = start;
			int middleIndex = (end - start) / 2;
			if (ascArray[start + middleIndex] > val) {// 仍然大于改值需要向前继续二分查找
				end = start + middleIndex;
			} else if (ascArray[start + middleIndex] < val) {// 小于该值需要往后继续二分查找
				start = middleIndex + start;
			} else {
				return middleIndex + start;
			}
		}
	}

	private static int swap(Integer[] dest, int i, int val) {
		try {
			return dest[i];
		} finally {
			dest[i] = val;
		}
	}

	public static int getMiddle(int low, int high) {
		int total = high - low;
		int middle;
		if (total % 2 == 0) {
			middle = total >>> 1;
		} else {
			middle = (total >>> 1) + 1;
		}
		if (low == 0) {
			return middle;
		} else {
			return middle + low;
		}
	}

}



归并排序

标签:算法

原文地址:http://blog.csdn.net/kevin_luan/article/details/37994837

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!