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.拓展内容