java算法之归并排序

61 篇文章 0 订阅

Android面试时经常也会被问到数据结构算法的问题,最近有时间,写点实例。

我模拟的场景是对一个班上学生成绩进行排名。

归并排序原理:

   假如有两个已经是有序的数组    [2  ,  7 ,   8]    [ 3   ,  5   ,  9],现在要把它们两个数组合并到一起变成一个有序数组。 

2<3 取2,

7>3 取3,

7>5 取5,

7<9   取7,

8<9 取8,

数组一取完了 最后取剩余的9。

最后你们把取得数连起来看看:2,3,5,7,8,9 已经变成有序的了,这是不是个很有趣的现象?归并就是基于这个现象来的。从上面要把大数组排序,就要求把大数组分成两个小数组,同时要求小数组是有序的,小数组怎么成为有序的呢?那就需要再把小数组分成两个更小的数组,同时两个更小的数组也需要是有序的。。。你有没有发现这里面有个死循环?这就是我们递归的存在,递归总有个结束的位置,那就是当子数组划分到最小只有一个元素时,那它默认就是有序的。所有反过来看,先是两个只有1个元素的数组通过上面的比较算法合并成一个有2个元素的有序数组,然后两个有2个元素的子数组通过上面的比较算法合并成一个有4个元素的有序书数组。。。最后最大的那个数组就成了有序的了。


1.Person.Java实体类

package com.demo.sort;
public class Person {
	/**
	 * 名字
	 */
	public String name;
	
	/**
	 * 分数
	 */
	public int score;

	public Person(String name, int score) {
		super();
		this.name = name;
		this.score = score;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	public String toString() {
		return ""+score+"";
	}
}
2.准备数据

package com.demo.sort;
public class DataUtil {
	Person person1 = new Person("张一",60);
	Person person2 = new Person("张二",82);
	Person person3 = new Person("张三",23);
	Person person4 = new Person("张四",31);
	Person person5 = new Person("张五",55);
	Person person6 = new Person("张六",89);
	Person person7 = new Person("张七",92);
	Person person8 = new Person("张八",48);
	Person person9 = new Person("张九",50);
	Person person10 = new Person("张十",23);
	Person [] persons = {
				person1,person2,person3,person4,person5,
				person6,person7,person8,person9,person10
			};
	public Person[] getData(){
		return persons;
	}
}
3. 归并排序

package com.demo.sort;

/**
 * 归并排序
 * 
 * @author http://blog.csdn.net/nnmmbb
 * 
 */
public class SortDemo {
	public static void main(String args[]) {
		Person[] persons = new DataUtil().getData();
		beforeSort(persons);
		//归并排序
		mergeSort(persons,0,persons.length-1);
 
	}
	/**
	 * 归并排序
	 * @param persons
	 */
	private static void mergeSort(Person[] persons, int start, int end) {
		if (start < end) {
			// 分组
			int mid = (start + end) / 2;
			mergeSort(persons, start, mid);
			mergeSort(persons, mid+1, end);
			
			//合并
			doMergeSort(persons,start,mid,end);
		}
		
	}
	
	private static void doMergeSort(Person []persons,int start,int mid ,int end){
	     
		int index = 0;
		int index1 = start;
		int index2 = mid + 1;
		//创建一个临时数组,数组的长度等于这一轮需要合并的两部分长度之和
		Person [] temp = new Person[end - start + 1];
		
		System.out.printf("\n开始合并,合并范围,[%d,%d],[%d,%d]", index1, mid,index2,end);  
		
		//将前后两段数组小的放到临时数组里
		while(index1 <= mid && index2<=end){
			if(persons[index1].score <= persons[index2].score){
				temp[index++] = persons[index1++];
			}else{
				temp[index++] = persons[index2++];
			}
		}
		
		// 如果上的操作做完了,但第一段数组还没遍历完,就把剩下的全部拷贝到临时数组里。
		while(index1<=mid){
			temp[index++] = persons[index1++];
		}
		
		// 如果上的操作做完了,但第二段数组还没遍历完,就把剩下的全部拷贝到临时数组里。
		while(index2<=end){
			temp[index++] = persons[index2++];	
		}
		
		//将从start开始,长度为k的临时数组拷贝到原数组的[start-->start+k]的位置
		for(int k=0;k<temp.length;k++){
			persons[start+k] = temp[k];
		}
		
		printArray(persons);
	}
	
	
	private static void printArray(Person [] persons){
		    System.out.print("\n下标:");  
	        for (int p = 0; p < persons.length; p++) {  
	            System.out.printf("%2d,", p);  
	        }  
	        System.out.print("\n值值:");  
	        for (Person m : persons) {  
	            System.out.printf("%2d,", m.score);  
	        }  
	        System.out.print("\n-----------------------------");  
	}
	private static void beforeSort(Person[] persons) {
		System.out.print("before sort:");
		for (int i = 0; i < persons.length; i++) {
			System.out.print(" " + persons[i].toString());
		}
		System.out.println();
		System.out.println();
	}

}

4.结果演示

before sort: 60 82 23 31 55 89 92 48 50 23


开始合并,合并范围,[0,0],[1,1]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:60,82,23,31,55,89,92,48,50,23,
-----------------------------
开始合并,合并范围,[0,1],[2,2]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,60,82,31,55,89,92,48,50,23,
-----------------------------
开始合并,合并范围,[3,3],[4,4]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,60,82,31,55,89,92,48,50,23,
-----------------------------
开始合并,合并范围,[0,2],[3,4]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,31,55,60,82,89,92,48,50,23,
-----------------------------
开始合并,合并范围,[5,5],[6,6]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,31,55,60,82,89,92,48,50,23,
-----------------------------
开始合并,合并范围,[5,6],[7,7]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,31,55,60,82,48,89,92,50,23,
-----------------------------
开始合并,合并范围,[8,8],[9,9]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,31,55,60,82,48,89,92,23,50,
-----------------------------
开始合并,合并范围,[5,7],[8,9]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,31,55,60,82,23,48,50,89,92,
-----------------------------
开始合并,合并范围,[0,4],[5,9]
下标: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
值值:23,23,31,48,50,55,60,82,89,92,
-----------------------------

5.拓展内容


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值