zoukankan      html  css  js  c++  java
  • 数据结构与算法——桶排序以及排序大总结(1)

    比较器的使用

    1) 比较器的实质就是重载比较运算符

    2) 比较器可以很好的应用在特殊标准的排序上

    3) 比较器可以很好的应用在根据特殊标准排序的结构上

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.PriorityQueue;
    import java.util.TreeSet;
    
    public class Code03_Comparator {
    
    	public static class Student {
    		public String name;
    		public int id;
    		public int age;
    
    		public Student(String name, int id, int age) {
    			this.name = name;
    			this.id = id;
    			this.age = age;
    		}
    	}
    
    	public static class IdAscendingComparator implements Comparator<Student> {
    		// 返回负数的时候,第一个参数排在前面。返回正数的时候,第二个参数排在前面。
            // 返回0的时候,谁在前面无所谓。
    		@Override
    		public int compare(Student o1, Student o2) {
    			return o1.id - o2.id;
    		}
    	}
    
    	public static class IdDescendingComparator implements Comparator<Student> {
    		
            @Override
    		public int compare(Student o1, Student o2) {
    			return o2.id - o1.id;
    		}
    	}
    
    	public static class AgeAscendingComparator implements Comparator<Student> {
    
    		@Override
    		public int compare(Student o1, Student o2) {
    			return o1.age - o2.age;
    		}
    	}
    
    	public static class AgeDescendingComparator implements Comparator<Student> {
    
    		@Override
    		public int compare(Student o1, Student o2) {
    			return o2.age - o1.age;
    		}
    	}
    
    	public static void printStudents(Student[] students) {
    		for (Student student : students) {
    			System.out.println("Name : " + student.name + ", Id : " + student.id + ", Age : " + student.age);
    		}
    	}
    
    	public static void printArray(Integer[] arr) {
    		if (arr == null) {
    			return;
    		}
    		for (int i = 0; i < arr.length; i++) {
    			System.out.print(arr[i] + " ");
    		}
    		System.out.println();
    	}
    
    	public static class MyComp implements Comparator<Integer> {
    
    		@Override
    		public int compare(Integer o1, Integer o2) {
    			return o2 - o1;
    		}
    	}
    
    	public static void main(String[] args) {
    		Student student1 = new Student("A", 2, 23);
    		Student student2 = new Student("B", 3, 21);
    		Student student3 = new Student("C", 1, 22);
    
    		Student[] students = new Student[] { student1, student2, student3 };
    
    		Arrays.sort(students, new IdAscendingComparator());
    		printStudents(students);
    
    		Arrays.sort(students, new IdDescendingComparator());
    		printStudents(students);
    
    		Arrays.sort(students, new AgeAscendingComparator());
    		printStudents(students);
    
    		Arrays.sort(students, new AgeDescendingComparator());
    		printStudents(students);
    
    		PriorityQueue<Student> maxHeapBasedAge = new PriorityQueue<>(new AgeDescendingComparator());
    		maxHeapBasedAge.add(student1);
    		maxHeapBasedAge.add(student2);
    		maxHeapBasedAge.add(student3);
    		while (!maxHeapBasedAge.isEmpty()) {
    			Student student = maxHeapBasedAge.poll();
    			System.out.println("Name : " + student.name + ", Id : " + student.id + ", Age : " + student.age);
    		}
    
    		PriorityQueue<Student> minHeapBasedId = new PriorityQueue<>(new IdAscendingComparator());
    		minHeapBasedId.add(student1);
    		minHeapBasedId.add(student2);
    		minHeapBasedId.add(student3);
    		while (!minHeapBasedId.isEmpty()) {
    			Student student = minHeapBasedId.poll();
    			System.out.println("Name : " + student.name + ", Id : " + student.id + ", Age : " + student.age);
    		}
    
    		TreeSet<Student> treeAgeDescending = new TreeSet<>(new AgeDescendingComparator());
    		treeAgeDescending.add(student1);
    		treeAgeDescending.add(student2);
    		treeAgeDescending.add(student3);
    
    		Student studentFirst = treeAgeDescending.first();
    		System.out.println("Name : " + studentFirst.name + ", Id : " + studentFirst.id + ", Age : " + studentFirst.age);
    
    		Student studentLast = treeAgeDescending.last();
    		System.out.println("Name : " + studentLast.name + ", Id : " + studentLast.id + ", Age : " + studentLast.age);
    	}
    }
    

    桶排序思想下的排序

    1) 计数排序

    2) 基数排序

    分析:

    1) 桶排序思想下的排序都是不基于比较的排序

    2) 时间复杂度为O(N),额外空间负载度O(M)

    3) 应用范围有限,需要样本的数据状况满足桶的划分

    	// only for no-negative value
    	public static void radixSort(int[] arr) {
    		if (arr == null || arr.length < 2) {
    			return;
    		}
    		radixSort(arr, 0, arr.length - 1, maxbits(arr));
    	}
    
    	public static int maxbits(int[] arr) {
    		int max = Integer.MIN_VALUE;
    		for (int i = 0; i < arr.length; i++) {
    			max = Math.max(max, arr[i]);
    		}
    		int res = 0;
    		while (max != 0) {
    			res++;
    			max /= 10;
    		}
    		return res;
    	}
    
    	//arr[begin,end]排序
    	public static void radixSort(int[] arr, int begin, int end, int digit) {
    		final int radix = 10;
    		int i = 0, j = 0;
    
    		int[] bucket = new int[end - begin + 1]; //有多少个数准备多少辅助空间
    		for (int d = 1; d <= digit; d++) { //有多少位就进出多少次
    			int[] count = new int[radix];
    			for (i = begin; i <= end; i++) { //10个空间 count[0] 当前位(d位)是0的数字有多少个
    				j = getDigit(arr[i], d);
    				count[j]++;
    			}
    			for (i = 1; i < radix; i++) {
    				count[i] = count[i] + count[i - 1];
    			}
    			for (i = end; i >= begin; i--) {
    				j = getDigit(arr[i], d);
    				bucket[count[j] - 1] = arr[i];
    				count[j]--;
    			}
    			for (i = begin, j = 0; i <= end; i++, j++) {
    				arr[i] = bucket[j];
    			}
    		}
    	}
    
    	public static int getDigit(int x, int d) {
    		return ((x / ((int) Math.pow(10, d - 1))) % 10);
    	}
    

    排序算法的稳定性及其汇总

    同样值的个体之间,如果不因为排序而改变相对次序,就是这个排序是有稳定 性的;否则就没有。

    不具备稳定性的排序:

    选择排序、快速排序、堆排序

    具备稳定性的排序:

    冒泡排序、插入排序、归并排序、一切桶排序思想下的排序

    目前没有找到时间复杂度0(N*logN),额外空间复杂度0(1),又稳定的排序。

    常见的坑

    1, 归并排序的额外空间复杂度可以变成0(1),但是非常难,不需要掌握,有兴趣可以搜“归并排序内部缓存法”

    2, “原地归并排序”的帖子都是垃圾,会让归并排序的时间复杂度变成0(N^2)

    3, 快速排序可以做到稳定性问题,但是非常难,不需要掌握,可以搜“01 stable sort”

    4, 所有的改进都不重要,因为目前没有找到时间复杂度0(N*logN),额外空间复 杂度0(1),又稳定的排序。

    5, 有一道题目,是奇数放在数组左边,偶数放在数组右边,还要求原始的相对 次序不变,碰到这个问题,可以怼面试官。

    工程上对排序的改进

    1. 充分利用O(N* logN)和0 (N^2)排序各自的优势

    大样本 快排

    小样本 插入

    1. 稳定性的考虑

    基础类型 快排

    自己规定类型 归并

  • 相关阅读:
    BZOJ 3924: [Zjoi2015]幻想乡战略游戏
    codevs 4244 平衡树练习
    BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
    BZOJ 2038: [2009国家集训队]小Z的袜子
    luogu P3709 大爷的字符串题
    BZOJ 2120: 数颜色
    luogu P2056 采花
    luogu P2709 小B的询问
    BZOJ 1878: [SDOI2009]HH的项链
    Codeforces 221d D. Little Elephant and Array
  • 原文地址:https://www.cnblogs.com/wwj99/p/12196081.html
Copyright © 2011-2022 走看看