分组排序的一个实现

问题如下:

有一排红黑混合的球,标有重复数字无序排列,例如:{R3, R1, B2, B4, R1, R4, R2, B1, B3, B2, B1}。现在希望进行先红后黑由小到大的排序,并且这些球原先所在位置的下标要由小到大(红黑区别)

思路如下:

1、此题目主要考察对排序算法中的稳定排序的熟悉程度
2、稳定排序中主要考虑冒泡和归并(JDK中的Arrays.sort就是使用mergeSort)两种排序


Ball类

import lombok.Data;

@Data
public class Ball {

    private Integer id; // 球号码

    private String color; // red || black

    private Integer index; // 球下标

    public Ball() {}

    public Ball(Integer id, String color) {
        this.id = id;
        this.color = color;
    }

    public Ball(Integer id, String color, Integer index) {
        this.id = id;
        this.color = color;
        this.index = index;
    }

}

冒泡排序的实现如下:

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.Data;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
public class BallBubbleSort {

    private Map<String, Ball[]> result = new HashMap<String, Ball[]>();

    public Map<String, Ball[]> sort(Ball[] balls) {
        Ball[] reds = assemblyBallArray(balls, "Red");
        Ball[] blacks = assemblyBallArray(balls, "Black");

        bubbleSortLowAndHigh(reds);
        bubbleSortLowAndHigh(blacks);

        Map<String, Ball[]> result = new HashMap<String, Ball[]>();
        result.put("Red", reds);
        result.put("Black", blacks);
        return result;
    }

    public void sort2(Ball[] balls) {
        Ball[] reds = assemblyBallArray(balls, "Red");
        Ball[] blacks = assemblyBallArray(balls, "Black");

        bubbleSortLowAndHigh(reds);
        bubbleSortLowAndHigh(blacks);

        result.put("Red", reds);
        result.put("Black", blacks);
    }

    public Ball[] assemblyBallArray(Ball[] balls, String type) {
        List<Ball> res = Lists.newArrayList();
        for (Ball ball : balls) {
            if (ball.getColor().equals(type)) res.add(ball);
        }
        return res.toArray(new Ball[res.size()]);
    }

    /*public Ball[] assemblyBallArray(Ball[] balls, String type) {
        List<Ball> ballList = null;
        if (ballList == null) {
            ballList = Lists.newArrayList();
            for (Ball ball : balls) {
                if (ball.getColor().equals(type)) ballList.add(ball);
            }
        }
        List<Ball> res = ballList;
        ballList = null;
        return res.toArray(new Ball[res.size()]);
    }*/

    public void bubbleSortBall(Ball[] balls) {
        for (int k = 0; k < balls.length; k++) {
            balls[k].setIndex(k);
        }

        for (int i = 0; i < balls.length - 1; i++) {
            for (int j = 0; j < balls.length - i - 1; j++) {
                if(balls[j].getId() > balls[j+1].getId()) {
                    Ball tmp = balls[j];
                    balls[j] = balls[j+1];
                    balls[j+1] = tmp;
                }
            }
        }
    }

    public void bubbleSortBallOptimizePos(Ball[] balls) {
        for (int k = 0; k < balls.length; k++) {
            balls[k].setIndex(k);
        }

        int arrLen = balls.length - 1; //初始时,最后位置保持不变
        while (arrLen > 0) {
            int pos = 0; //每趟开始时,无记录交换
            for (int i = 0; i < arrLen; i++) {
                if(balls[i].getId() > balls[i + 1].getId()) {
                    pos = i; //记录交换的位置
                    Ball tmp = balls[i];
                    balls[i] = balls[i + 1];
                    balls[i + 1] = tmp;
                    System.out.println("pos -> " + pos);
                }
            }
            arrLen = pos; //为下一趟排序作准备
            System.out.println("arrLen -> " + arrLen);
        }
    }

    public void bubbleSortLowAndHigh(Ball[] balls) {
        for (int k = 0; k < balls.length; k++) {
            balls[k].setIndex(k);
        }

        int low = 0;
        int high= balls.length-1; //设置变量的初始值
        int j = 0;
        Ball tmp = null;
        while (low < high) {
            for (j = low; j < high; ++j) { //正向冒泡,找到最大者
                if (balls[j].getId() > balls[j + 1].getId()) {
                    tmp = balls[j]; balls[j]=balls[j + 1];balls[j + 1]=tmp;
                }
            }
            --high; //修改high值, 前移一位
            for (j = high; j>low; --j) { //反向冒泡,找到最小者
                if (balls[j].getId() <balls[j - 1].getId()) {
                    tmp = balls[j]; balls[j]=balls[j - 1];balls[j - 1]=tmp;
                }
            }
            ++low; //修改low值,后移一位
        }
    }

    public static void main(String[] args) {

        Ball R1 = new Ball(1, "Red");
        Ball R2 = new Ball(3, "Red");
        Ball R3 = new Ball(4, "Red");
        Ball R4 = new Ball(2, "Red");
        Ball R5 = new Ball(1, "Red");


        Ball B1 = new Ball(2, "Black");
        Ball B2 = new Ball(4, "Black");
        Ball B3 = new Ball(1, "Black");
        Ball B4 = new Ball(3, "Black");

        Ball[] balls = {R3, R1, B2, B4, R4, B1, R2, B3, R5};


        BallBubbleSort ballBubbleSort = new BallBubbleSort();

        ballBubbleSort.sort2(balls);

        System.out.println(JSON.toJSONString(ballBubbleSort.getResult()));

//        System.out.println(JSON.toJSONString(ballBubbleSort.sort(balls)));

        /* 默认冒泡算法复杂度 */

        int[] a = {3, 1, 4, 1, 2};

        int countOutside1 = 0;
        int countInside1 = 0;
        for(int i =0 ; i< a.length-1; i++) {
            countOutside1++;
            for(int j = 0; j < a.length-i-1; j++) {
                countInside1++;
                if(a[j] > a[j+1])
                {
                    int tmp = a[j] ; a[j] = a[j+1] ;  a[j+1] = tmp;
                }
            }
        }
        System.out.println(countOutside1);
        System.out.println(countInside1);

        /* 第一种改良冒泡算法复杂度 */

        int[] b = {3, 1, 4, 1, 2};

        int countOutside2 = 0;
        int countInside2 = 0;
        int arrLen = b.length - 1;
        while (arrLen > 0) {
            countOutside2++;
            int pos = 0;
            for (int i = 0; i < arrLen; i++) {
                countInside2++;
                if(b[i] > b[i + 1]) {
                    pos = i;
                    int tmp = b[i] ; b[i] = b[i+1] ;  b[i+1] = tmp;
                }
            }
            arrLen = pos;
        }
        System.out.println("======");
        System.out.println(countOutside2);
        System.out.println(countInside2);

        /* 第二种改良冒泡算法复杂度 */

        int[] c = {3, 1, 4, 1, 2};

        int countOutside3 = 0;
        int countInside3To1 = 0;
        int countInside3To2 = 0;
        int low = 0;
        int high= c.length-1;
        int tmp,j;
        while (low < high) {
            countOutside3++;
            for (j= low; j< high; ++j) {
                countInside3To1++;
                if (c[j]> c[j+1]) {
                    tmp = c[j]; c[j]=c[j+1];c[j+1]=tmp;
                }
            }
            --high;
            for (j=high; j>low; --j) {
                countInside3To2++;
                if (c[j]<c[j-1]) {
                    tmp = c[j]; c[j]=c[j-1];c[j-1]=tmp;
                }
            }
            ++low;
        }
        System.out.println("======");
        System.out.println(countOutside3);
        System.out.println(countInside3To1);
        System.out.println(countInside3To2);

        System.out.println("POP Sort ->" + JSON.toJSONString(a));
        System.out.println("POP Sort ->" + JSON.toJSONString(b));
        System.out.println("POP Sort ->" + JSON.toJSONString(c));
    }
}

归并排序的实现如下:

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.Data;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
public class BallMergeSort {

    private Map<String, Ball[]> result = new HashMap<String, Ball[]>();

    public void mergearray(Ball[] balls, int first, int mid, int last, Ball[] temp) {
        int i = first, j = mid + 1;
        int m = mid,   n = last;
        int k = 0;

        while (i <= m && j <= n)
        {
            if (balls[i].getId() <= balls[j].getId())
                temp[k++] = balls[i++];
            else
                temp[k++] = balls[j++];
        }

        while (i <= m)
            temp[k++] = balls[i++];

        while (j <= n)
            temp[k++] = balls[j++];

        for (i = 0; i < k; i++)
            balls[first + i] = temp[i];
    }

    public void mergesort(Ball[] balls, int first, int last, Ball[] temp) {
        if (first < last)
        {
            int mid = (first + last) / 2;
            mergesort(balls, first, mid, temp);    //左边有序
            mergesort(balls, mid + 1, last, temp); //右边有序
            mergearray(balls, first, mid, last, temp); //再将二个有序数列合并
        }
    }

    public boolean MergeSort(Ball[] balls, int n) {
        for (int k = 0; k < balls.length; k++) {
            balls[k].setIndex(k);
        }

        Ball[] p = new Ball[n];
        if (p == null)
            return false;
        mergesort(balls, 0, n - 1, p);
        return true;
    }

    public void sort(Ball[] balls) {
        for (int k = 0; k < balls.length; k++) {
            balls[k].setIndex(k);
        }

        Ball[] reds = assemblyBallArray(balls, "Red");
        Ball[] blacks = assemblyBallArray(balls, "Black");

        Ball[] redsTmp = new Ball[reds.length];
        Ball[] blacksTmp = new Ball[blacks.length];

        mergesort(reds, 0, reds.length - 1, redsTmp);
        mergesort(blacks, 0, blacks.length - 1, blacksTmp);

        result.put("Red", reds);
        result.put("Black", blacks);
    }

    public Ball[] assemblyBallArray(Ball[] balls, String type) {
        List<Ball> res = Lists.newArrayList();
        for (Ball ball : balls) {
            if (ball.getColor().equals(type)) res.add(ball);
        }
        return res.toArray(new Ball[res.size()]);
    }

    public static void main(String[] args) {

        Ball R1 = new Ball(1, "Red");
        Ball R2 = new Ball(3, "Red");
        Ball R3 = new Ball(4, "Red");
        Ball R4 = new Ball(2, "Red");
        Ball R5 = new Ball(1, "Red");


        Ball B1 = new Ball(2, "Black");
        Ball B2 = new Ball(4, "Black");
        Ball B3 = new Ball(1, "Black");
        Ball B4 = new Ball(3, "Black");

        Ball[] balls = {R3, R1, B2, B4, R4, B1, R2, B3, R5};

//        Ball[] balls = {R3, R1, R4, R2, R5};

        BallMergeSort ballMergeSort = new BallMergeSort();

//        ballMergeSort.MergeSort(balls, balls.length);

        ballMergeSort.sort(balls);

        System.out.println(JSON.toJSONString(ballMergeSort.getResult()));

    }
}

阿莫斯论Amos

posted @ 2017-03-08 15:37  Andrew.Zhou  阅读(530)  评论(0编辑  收藏  举报