分组排序的一个实现
问题如下:
有一排红黑混合的球,标有重复数字无序排列,例如:{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()));
}
}