数据结构与算法-排序算法-partial

前言

都什么时代了,还写排序算法的总结?

原因有二。一是别人的精彩永远是别人的,你只有鼓掌的份儿;有些事情实际动手去做了才会有所体会。

二是排序算法是一类基础类的算法,不光是IT从业者真正入门的门槛,也是一些高级算法的关键部分或算法评估的benchmark。

计划说明的算法内容有哪些? 

算法的思想、Java代码实现和平均算法复杂度、算法运行完整示例。

参考文献有哪些?

wiki[EB/OL]

Shaffer C. A. Data Structure and Algorithm Analysis in Java, 3rd Edition[M]. Dover Publications, New York. 2011.

 

目录

0 实现工具类

1 插入排序

2 选择排序

3 冒泡排序

4 合并排序

5 堆排序

6 快速排序

7 桶排序

8 基数排序

9 外排序

10 Funny methods

 

 

 

内容

0 实现工具类

//时间费用注解

/**

 * Description: 时间费用注解<br/>

 * Date: 2014-4-26 下午4:49:39

 */

public @interface Expense {

    /** 标记 */

    TAG tag();



    /***/

    String value();



    enum TAG {

        Θ, Ο, Ω

    }

}
View Code

 

//数据结构与算法工具类

package util;



/**

 * 

 *    Description: 数据结构与算法工具类<br/>

 * Date: 2014-5-6 下午10:27:18

 */

public class DSUtil {

    // 单元测试

    public static void main(String[] args) {

        Integer[] A = { 1, 2, 3, 4, 5 };

        println(A);

        swap(A, 1, 3);

        println(A);

    }



    public static Integer[] SORT_TEST_ARRAY = new Integer[] { 42, 20, 17, 13, 28, 14, 23, 15 };



    public static <E> void swap(E[] A, int i, int j) {

        E temp = A[i];

        A[i] = A[j];

        A[j] = temp;

    }



    public static <E> void println(E[] A) {

        for (E a : A) {

            System.out.print(a + " ");

        }

        System.out.println();

    }



}
View Code

 

//排序方法算法接口 - 一般用Integer数组表示待排序列表

package internalsort;



/**

 * Description: 排序方法算法接口<br/>

 * Date: 2014-5-5 下午10:46:52

 */

public interface Sort<E extends Comparable<? super E>> {

    /**

     * Description: 将E元素数组A排序<br/>

     * PRE: <br/>

     * POST: <br/>

     */

    void sort(E[] A);

}
View Code

 

 

1 插入排序

 

package internalsort;



import util.DSUtil;

import util.Expense;



/**

 * Description: 插入排序<br/>

 * 思想:从列表第二个元素开始直到列表末尾,一次将每个元素放置到正确的位置<br/>

 * Date: 2014-5-5 下午10:43:54

 */

public class InsertionSort implements Sort<Integer> {



    /* @see internalsort.Sort#sort(E[]) */

    @Override

    @Expense(tag = Expense.TAG.Θ, value = "n^2")

    public void sort(Integer[] A) {

        int n = A.length;

        for (int i = 1; i < n; i++) {//从第二个元素开始,直至列表末尾

            for (int j = i; j > 0; j--) {//从i开始向列表头部,若j处值<j-1处值,交换两者位置

                if (A[j] < A[j - 1]) {

                    DSUtil.swap(A, j, j - 1);

                }

            }

        }

    }



    public static void main(String[] args) {

        InsertionSort service = new InsertionSort();

        Integer[] A = DSUtil.SORT_TEST_ARRAY;



        DSUtil.println(A);

        service.sort(A);

        DSUtil.println(A);

    }

}
View Code

 

 

2 选择排序

 

package internalsort;



import util.DSUtil;

import util.Expense;



/**

 * Description: 选择排序<br/>

 * 思想:从列表头部开始,将当前位置的值与后面的最小值交换<br/>

 * Date: 2014-5-5 下午11:15:30

 */

public class SelectionSort implements Sort<Integer> {



    /* @see internalsort.Sort#sort(E[]) */

    @Override

    @Expense(tag = Expense.TAG.Θ, value = "n^2")

    public void sort(Integer[] A) {

        int n = A.length;

        for (int i = 0; i < n - 1; i++) {

            int smallestIndex = i;

            for (int j = i + 1; j < n; j++) {

                if (A[smallestIndex] > A[j]) {

                    smallestIndex = j;

                }

            }

            DSUtil.swap(A, i, smallestIndex);

        }

    }



    //方法1:缺陷交换次数过多

    public void sort1(Integer[] A) {

        int n = A.length;

        for (int i = 0; i < n - 1; i++) {

            for (int j = i + 1; j < n; j++) {

                if (A[i] > A[j]) {

                    DSUtil.swap(A, i, j);

                }

            }

        }

    }



    public static void main(String[] args) {

        SelectionSort service = new SelectionSort();

        Integer[] A = DSUtil.SORT_TEST_ARRAY;



        DSUtil.println(A);

        service.sort(A);

        DSUtil.println(A);

    }

}
View Code

 

 

3 冒泡排序

 

package internalsort;



import util.DSUtil;

import util.Expense;



/**

 * Description: 冒泡排序<br/>

 * 思想:第i遍将第i小值排好序<br/>

 * Date: 2014-5-5 下午11:01:56

 */

public class BubbleSort implements Sort<Integer> {



    /* @see internalsort.Sort#sort(E[]) */

    @Override

    @Expense(tag = Expense.TAG.Θ, value = "n^2")

    public void sort(Integer[] A) {

        int n = A.length;

        for (int i = 0; i < n - 1; i++) {//遍数标识,共需n-1遍

            for (int j = n - 1; j > i; j--) {//内部循环从列表尾部开始

                if (A[j] < A[j - 1]) {//小元素上升

                    DSUtil.swap(A, j, j - 1);

                }

            }

        }

    }



    public static void main(String[] args) {

        BubbleSort service = new BubbleSort();

        Integer[] A = DSUtil.SORT_TEST_ARRAY;



        DSUtil.println(A);

        service.sort(A);

        DSUtil.println(A);

    }

}
View Code

 

 

4 合并排序

 

package internalsort;



import util.DSUtil;

import util.Expense;



/**

 * Description: 合并排序<br/>

 * 思想:依然是分治策略,将待排序划分为两个子序列,分别将左右两个子序列排好序后将两个子序列合并<br/>

 * Date: 2014-5-6 下午9:32:14

 */

public class MergeSort implements Sort<Integer> {



    /* @see internalsort.Sort#sort(E[]) */

    @Override

    @Expense(tag = Expense.TAG.Θ, value = "nlogn")

    public void sort(Integer[] A) {

        Integer[] deepCopy = new Integer[A.length];

        for (int i = 0; i < A.length; i++) {

            deepCopy[i] = A[i];

        }

        //version 1

        //        int n = A.length;

        //        Integer[] A2 = new Integer[n];

        //        for (int i = 0; i < n; i++) {//注意要初始化

        //            A2[i] = 0;

        //        }

        //        mergeSort(A, A2, 0, n - 1);



        //version 2

        mergeSortV2(A, 0, A.length - 1);

        DSUtil.println(deepCopy);

    }



    private void mergeSort(Integer[] A, Integer[] A2, int l, int r) {

        if (l == r) return;

        int mid = (l + r) / 2;

        mergeSort(A, A2, l, mid);

        mergeSort(A, A2, mid + 1, r);

        for (int i = l; i <= r; i++) {//[l, r]

            A2[i] = A[i];

        }

        int i = l, j = mid + 1;//左右子列表的索引

        for (int curr = l; curr <= r; curr++) {//[l, r]

            if (i == mid + 1) {//左子列表空

                A[curr] = A2[j++];

            } else if (j > r) {//右子列表空

                A[curr] = A2[i++];

            } else if (A2[i] < A2[j]) {//选择较小的值

                A[curr] = A2[i++];

            } else {

                A[curr] = A2[j++];

            }

        }

    }



    private void mergeSortV2(Integer[] A, int l, int r) {

        if (l == r) return;

        int mid = (l + r) / 2;

        mergeSortV2(A, l, mid);

        mergeSortV2(A, mid + 1, r);

        merge(A, l, r);

    }



    private void merge(Integer[] A, int l, int r) {

        int mid = (l + r) / 2;

        Integer[] A2 = new Integer[r + 1];

        for (int i = l; i <= r; i++) {//[l, r]

            A2[i] = A[i];

        }

        int i = l, j = mid + 1;//左右子列表的索引

        for (int curr = l; curr <= r; curr++) {//[l, r]

            if (i == mid + 1) {//左子列表空

                A[curr] = A2[j++];

            } else if (j > r) {//右子列表空

                A[curr] = A2[i++];

            } else if (A2[i] < A2[j]) {//选择较小的值

                A[curr] = A2[i++];

            } else {

                A[curr] = A2[j++];

            }

        }

    }



    public static void main(String[] args) {

        MergeSort service = new MergeSort();

        Integer[] A = DSUtil.SORT_TEST_ARRAY;



        DSUtil.println("Before", A);

        service.sort(A);

        DSUtil.println("After", A);

    }

}
View Code

 

在DSUtil工具类中添加方法

    public static <E> void println(String comment, E[] A) {

        System.out.print(comment + ": ");

        for (E a : A) {

            System.out.print(a + " ");

        }

        System.out.println();

    }
View Code

 

5 堆排序

 

package internalsort;



import tree.heap.MaxHeap;

import util.DSUtil;

import util.Expense;



/**

 * Description: 堆排序<br/>

 * 思想:将待排序列表组织成最大堆,依次移除最大元素,因最大堆实现中移除的元素放置于当前堆的末尾位置,故最终得到排好序的列表<br/>

 * Date: 2014-5-9 下午11:17:23

 */

public class HeapSort implements Sort<Integer> {



    /* @see internalsort.Sort#sort(E[]) */

    @Override

    @Expense(tag = Expense.TAG.Θ, value = "nlogn")

    public void sort(Integer[] A) {

        int n = A.length;

        MaxHeap<Integer> maxHeap = new MaxHeap<Integer>(A, n, n);

        for (int i = 0; i < n; i++) {//依次移除最大值,放于当前堆的末尾

            maxHeap.removemax();

        }

    }



    public static void main(String[] args) {

        HeapSort service = new HeapSort();

        Integer[] A = DSUtil.SORT_TEST_ARRAY;



        DSUtil.println(A);

        service.sort(A);

        DSUtil.println(A);

    }

}
View Code

 

最大堆实现类

package tree.heap;



import org.junit.Assert;



import util.Expense;



/**

 * Description: 最大堆<br/>

 * 性质:父节点值>= 左、右节点值

 * Date: 2014-4-27 下午11:34:32

 */

public class MaxHeap<E extends Comparable<? super E>> {

    private E[] heap;//内部数组

    private int size;//最大容量

    private int n;//当前容量



    public MaxHeap(E[] heap, int currentSize, int maxSize) {

        this.heap = heap;

        this.n = currentSize;

        this.size = maxSize;

        buildheap();

    }



    /**

     * Description: 构建堆<br/>

     * PRE: <br/>

     * POST: <br/>

     */

    @Expense(tag = Expense.TAG.Θ, value = "n")

    private void buildheap() {

        //将每个内部节点放置到正确的位置

        for (int i = n / 2 - 1; i >= 0; i--)

            siftdown(i);

    }



    /**

     * Description: 将元素放置在正确的位置:与其子节点值最大者交换位置,一直向下处理<br/>

     * PRE: <br/>

     * POST: <br/>

     */

    private void siftdown(int pos) {

        Assert.assertTrue("Heap postion out of range", pos >= 0 && pos < n);

        while (!isLeaf(pos)) {

            int childPos = leftChild(pos);//先选择左子节点位置

            if (childPos < (n - 1) && heap[childPos].compareTo(heap[childPos + 1]) < 0) {//若右子节点值较大,选择右子节点

                childPos++;

            }

            if (heap[pos].compareTo(heap[childPos]) >= 0) {//若该位置值大于其子节点的值,直接返回

                return;

            } else {//否则交换两者的值,继续

                swap(heap, pos, childPos);

                pos = childPos;

            }

        }

    }



    @Expense(tag = Expense.TAG.Θ, value = "logn")

    public E removemax() {

        Assert.assertTrue("Removing from empty heap", n > 0);

        swap(heap, 0, --n);//将最大值(root)与最后一位交换

        if (n != 0) {

            siftdown(0);//将新堆的root放置到正确的位置

        }

        return heap[n];//返回新堆的最后一个值

    }



    /**

     * Description: 删除堆中位置pos处的值<br/>

     * PRE: <br/>

     * POST: <br/>

     */

    public E remove(int pos) {

        Assert.assertTrue("Heap position out of range", pos >= 0 && pos < n);

        if (pos == (n - 1)) {//直接将堆最后一个值返回

            n--;

        } else {

            swap(heap, pos, --n);//将该位置值与堆中最后一个值交换

            //如果交换的值是一个大值,向上推, example 7362154 =(1)=> 746235,按层次输出 

            while ((pos > 0) && heap[pos].compareTo(heap[parent(pos)]) > 0) {

                swap(heap, pos, parent(pos));

                pos = parent(pos);

            }

            if (n != 0) {

                siftdown(pos);//如果交换的值是一个小值,向下推, example 7635432 =(6)=>753412

            }

        }

        return heap[n];

    }



    /**

     * Description:当前堆容量<br/>

     * PRE: <br/>

     * POST: <br/>

     */

    public int heapsize() {

        return n;

    }



    /**

     * Description: 若该位置是叶子的位置返回true<br/>

     * PRE: <br/>

     * POST: <br/>

     */

    public boolean isLeaf(int pos) {

        return (pos >= n / 2) && (pos < n);

    }



    public int leftChild(int pos) {

        Assert.assertTrue("Position has no left child", pos < n / 2);

        return 2 * pos + 1;

    }



    public int rightChild(int pos) {

        Assert.assertTrue("Position has no right child", pos < (n - 1) / 2);

        return 2 * pos + 2;

    }



    public int parent(int pos) {

        Assert.assertTrue("Position has no parent", pos > 0);

        return (pos - 1) / 2;

    }



    /**

     * Description: 插入值<br/>

     * PRE: <br/>

     * POST: <br/>

     */

    @Expense(tag = Expense.TAG.Θ, value = "logn")

    public void insert(E e) {

        Assert.assertTrue("Heap is full", n < size);

        int curr = n++;

        heap[curr] = e;

        //若curr的值大于其父节点的值,交换两者的位置

        while ((curr != 0) && heap[curr].compareTo(heap[parent(curr)]) > 0) {

            swap(heap, curr, parent(curr));

            curr = parent(curr);

        }

    }



    //交换数组中两个位置的值

    private void swap(E[] array, int pos1, int pos2) {

        E temp = array[pos1];

        array[pos1] = array[pos2];

        array[pos2] = temp;

    }



    @Override

    public String toString() {

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < n; i++) {

            sb.append(heap[i] + " ");

        }

        return sb.toString();

    }

}
View Code

 

 

6 快速排序

 

package internalsort;



import util.DSUtil;

import util.Expense;



/**

 * Description: 快速排序<br/>

 * 思想:将待排序列表按中心点pivot划分为两个子列表,将两个子列表分别排序后再合并<br/>

 * Date: 2014-5-6 下午9:03:56

 */

public class QuickSort {

    static Integer[] A = new Integer[] { 72, 6, 57, 88, 85, 42, 83, 73, 48, 60 };



    public static void main(String[] args) {

        DSUtil.println(A);



        // 测试partition

        // System.out.println(partition(A, -1, A.length - 1, 60));



        // 测试quickSort

        quickSort(A, 0, A.length - 1);

        DSUtil.println(A);

    }



    /**

     * 根据pivot划分A中[l, r]标识的子序列,返回pivot应该放置的位置索引<br/>

     * 此时左边的元素小于pivot,右边的元素大于pivot

     */

    @Expense(tag = Expense.TAG.Θ, value = "r-l+1")

    static int partition(Integer[] A, int l, int r, int pivotValue) {

        do {

            // 从小索引开始找值大于pivotValue的

            while (A[++l] < pivotValue);

            // 从大索引开始找值小于pivotValue的

            while ((r != 0) && A[--r] > pivotValue);

            // System.out.println("l=" + l + ", r=" + r);

            DSUtil.swap(A, l, r);

            // DSUtil.println(A);

        } while (l < r);

        // System.out.println("l=" + l + ", r=" + r);

        DSUtil.swap(A, l, r);

        // DSUtil.println(A);

        return l;

    }



    @Expense(tag = Expense.TAG.Θ, value = "nlogn")

    static void quickSort(Integer[] A, int i, int j) {

        int pivotIndex = findpivot(i, j);

        DSUtil.swap(A, pivotIndex, j);// 将中心点值放于数组末尾

        int pivotValue = A[j];

        int k = partition(A, i - 1, j, pivotValue);



        DSUtil.swap(A, k, j);// 将中心点值放在正确的位置



        // 递归处理左右子序列

        if ((k - i) > 1) {

            quickSort(A, i, k - 1);

        }

        if ((j - k) > 1) {

            quickSort(A, k + 1, j);

        }

    }



    // 定位中心点,方法1:中间点

    @Expense(tag = Expense.TAG.Θ, value = "1")

    static int findpivot(int i, int j) {

        return (i + j) / 2;

    }

}
View Code

 

 

7 桶排序

 

8 基数排序

 

9 外排序

 

10 Funny methods 

 

SleepSort, using Thread#sleep(ms)

public class SleepSort {

    public static void main(String[] args) {

        int[] ints = {1, 4, 7, 3, 8, 9, 2, 6, 5};

        SortThread[] sortThreads = new SortThread[ints.length];

        for (int i = 0; i < sortThreads.length; i++) {

            sortThreads[i] = new SortThread(ints[i]);

        }

        for (int i = 0; i < sortThreads.length; i++) {

            sortThreads[i].start();

        }

    }

}



class SortThread extends Thread {

    int ms = 0;



    public SortThread(int ms) {

        this.ms = ms;

    }



    public void run() {

        try {

            sleep(ms * 10 + 10);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println(ms);

    }

}
View Code

 

 

BogoSort

import java.util.Random;



public class Bogosort {



    public static void main(String[] args) {

        int[] array = new int[] {1, 4, 7, 3, 8, 9, 2, 6, 5};



        while (!isInOrder(array)) {

            permute(array);

            renderArray(array);

        }



    }



    private static final void renderArray(int[] array) {

        for (int a : array) {

            System.out.print(a + " ");

        }

        System.out.println();

    }



    private static <T> void permute(int[] array) {

        Random value = new Random();



        int radomPosition = 0;

        for (int i = array.length; i > 0; i--) {

            radomPosition = Math.abs(value.nextInt()) % i;

            if (radomPosition < 0) {

                radomPosition = -radomPosition;

            }

            swap(array, i - 1, radomPosition);

        }

    }



    private static void swap(int[] array, int p1, int p2) {

        int temp = array[p1];

        array[p1] = array[p2];

        array[p2] = temp;

    }



    private static boolean isInOrder(int[] array) {

        for (int i = 0; i < array.length - 1; i++) {

            if (array[i] > array[i + 1]) {

                return false;

            }

        }

        return true;

    }

}
View Code

 

 

 

你可能感兴趣的:(数据结构与算法)