Java比较器及初级排序实现

直接进入正题

什么是排序?

排序就是将一组对象按照某种逻辑顺序重新排列的过程

谈到排序必须先聊一下比较器
就 java 而言,有两个比较器接口 ComparableComparator
Comparable & Comparator 都是用来实现集合中元素的比较、排序的。

两者区别
Comparable 是在集合内部定义的方法实现的排序,称为内部比较器;Comparator 是在集合外部实现的排序,称为外部比较器。

Comparable 是对象自身实现比较接口,如 StringInteger 等,它们继承了 Comparable 接口,然后实现 comparaTo() 方法,也就是说这些类具有自比较功能,如下方 String 类部分源码所示:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
	...
	// 实现 comparaTo 方法
	public int compareTo(String anotherString) {
		int len1 = value.length;
		int len2 = anotherString.value.length;
		int lim = Math.min(len1, len2);
		char v1[] = value;
		char v2[] = anotherString.value;
		int k = 0;
		while (k < lim) {
			char c1 = v1[k];
			char c2 = v2[k];
			if (c1 != c2) return c1 - c2;
			k++;
		}
		return len1 - len2;
	}
	...
}

Comparator 是一个专用的比较器,当对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较

TreeSet<Long> treeSet = new TreeSet<Long>(new Comparator<Long>() {
	// 自定义 compare 方法
	public int compare(Long o1, Long o2) {
		return o1.compareTo(o2);
	}
});

使用案例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class AboutCompara {

	public static void main(String[] args) {
//		String 类内部实现的 compareTo 方法如下
		
//		public int compareTo(String anotherString) {
//	        int len1 = value.length;
//	        int len2 = anotherString.value.length;
//	        int lim = Math.min(len1, len2);
//	        char v1[] = value;
//	        char v2[] = anotherString.value;
//
//	        int k = 0;
//	        while (k < lim) {
//	            char c1 = v1[k];
//	            char c2 = v2[k];
//	            if (c1 != c2) {
//	                return c1 - c2;
//	            }
//	            k++;
//	        }
//	        return len1 - len2;
//	    }
		
		// String implement Comparable
		String[] arr = { "3", "1", "51", "7", "4" };
		Arrays.sort(arr);
		System.out.println(Arrays.toString(arr));
		
		System.out.println("--------- split line ---------");
		
		List<Integer> list = new ArrayList<Integer>();
		list.add(3);
		list.add(1);
		list.add(5);
		list.add(7);
		list.add(4);
		list.forEach(x -> System.out.print(x + " "));
		
		System.out.println("\n--------- split line ---------");
		
		list.sort(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return (o1 < o2) ? -1 : ((o1 == o2) ? 0 : 1);
			}
		});
		list.stream().forEach(System.out::println);
	}
}
/* 输出如下
[1, 3, 4, 51, 7]
--------- split line ---------
3 1 5 7 4 
--------- split line ---------
1
3
4
5
7
*/

初级排序
初级排序实现逻辑较简单,不多做解释,详见下方代码,主要介绍算法实现逻辑以及算法时间复杂度,空间复杂度,算法稳定性1

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * The {@code PrimarySort} class provides static methods for sorting an
 *  array using selection/bubble/insertion/shell sort.
 * @author Floyd
 */
@SuppressWarnings("rawtypes")
public class PrimarySort {
	
	/** Prevents instantiation. */
	private PrimarySort() {}
	
	/**
	 * Selection sort : 算法复杂度O(n^2) 空间复杂度O(1) 不稳
	 * <p>Rearranges the array in ascending order, using the natural order.
	 * @param a the array to be sorted
	 */
	public static void selectionSort(Comparable[] a) {
		int n = a.length;
		for (int i = 0; i < n - 1; i++) {
			for (int j = i + 1; j < n; j++) {
				if (less(a[j], a[i]))
					exch(a, i, j);
			}
		}
	}
	
	/**
	 * Selection sort 2 : 选择排序2 // 测试了下速度 没什么意义...
	 */
	public static void selectionSort2(Comparable[] a) {
		int n = a.length;
		for (int i = 0; i < n / 2; i++) {
			int max = i;
			for (int j = i + 1; j < n - i; j++) {
				if (less(a[j], a[i])) {
					exch(a, i, j);
				}
				if (less(a[max], a[j])) {
					max = j;
				}
			}
			exch(a, max, a.length - 1 - i);
		}
	}
	
	/**
	 * Bubble sort : 算法复杂度O(n^2) 空间复杂度O(1) 稳
	 */
	public static void bubbleSort(Comparable[] a) {
		int n = a.length;
		boolean b;
		for (int i = n - 1; i > 0; i--) {
			b = true;
			for (int j = 0; j < i; j++) {
				if (less(a[j + 1], a[j])) {
					exch(a, j, j + 1);
					b = false;
				}
			}
			if (b) break;
		}
	}
	
	/**
	 * Insertion sort : 算法复杂度O(n^2) 空间复杂度O(1) 稳
	 */
	public static void insertionSort(Comparable[] a) {
		int n = a.length;
		for (int i = 1; i < n; i++) {
			for (int j = i; j > 0 && less(a[j], a[j - 1]); j--) {
				exch(a, j, j - 1);
			}
		}
	}
	
	/**
	 * The {@code shellSort} fuction provides methods for sorting an
	 * array using Shell sort with Knuth's increment sequence (1, 4, 13, 40, ...).
	 * <p>算法复杂度O(n^1.3) 空间复杂度O(1) 不稳
	 * <p>Knuth's increment sequence
	 * <p>h = 3 * h + 1
	 */
	public static void shellSort(Comparable[] a) {
		int n = a.length;
		int h = 1;
		while (h <= n / 3)
			h = 3 * h + 1;
		while (h >= 1) {
			for (int i = h; i < n; i++) {
				for (int j = i; j >= h && less(a[j], a[j - h]); j -= h) {
					exch(a, j, j - h);
				}
			}
			h = h / 3;
		}
	}
	
	
	/*
	 * Helper sorting functions.
	 */
	/** exchange a[i] and a[j] */
    private static void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }
	
    /** is x < y ? */
    @SuppressWarnings("unchecked")
	private static boolean less(Comparable x, Comparable y) {
        return x.compareTo(y) < 0;
    }
	
	/** Check if array is sorted - useful for debugging. */
	private static boolean isSorted(Comparable[] a) {
		for (int i = 1; i < a.length; i++) {
			if (less(a[i], a[i - 1]))
				return false;
		}
		return true;
	}
	
	@SuppressWarnings("unused")
	public static void main(String[] args) {
		int num = 10000;
		int testTimes = 1;
		
		boolean flag = true;
		
		for (int k = 0; k < testTimes; k++) {
			
			for (int c = 0; ;c++) {
				
				Integer[] arr = new Integer[num];
				for (int i = 0; i < num; i++) {
					arr[i] = (int) (Math.random() * 100);
				}
			
				Date start = new Date();
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				if (c == 0) {
					System.out.println("Bubble sort");
					bubbleSort(arr);
				} else if (c == 1) {
					System.out.println("Selection sort");
					selectionSort(arr);
				} else if (c == 2) {
					System.out.println("Selection sort 2");
					selectionSort2(arr);
				} else if (c == 3) {
					System.out.println("Insertion sort");
					insertionSort(arr);
				} else if (c == 4) {
					System.out.println("Shell sort");
					shellSort(arr);
					flag = false;
				}
				Date end = new Date();
				
				if (isSorted(arr)) {
					System.out.println("spend : " + (end.getTime() - start.getTime()) + "ms");
				}
				
				if (!flag) break;
				
			}
			
		}
			
	}
}

写于一个睡不着的夜晚~


  1. 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值