排序算法动手研究

这段时间研究了一下排序算法,动手的感觉真好,学习算法也提高了兴趣。


public abstract class MySort {
    public int[] array;

    public abstract void sort();

    public MySort(int[] array) {
        this.array = array;
    }

    public void printArray(String desp, int[] array){
        System.out.println(desp);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

    public void exChangeElement(int[] array,int index,int largest){
        int value = array[index];
        array[index] = array[largest];
        array[largest] = value;
    }

    public static void main(String[] args) {
        int[] array = new int[]{9,8,2,53,23,2,321,232,467,54,78,54,34,3,998};
//        MySort algo = new HeapSort(array);
//        MySort algo = new InsertSort(array);
//        MySort algo = new MergeSort(array);
//        MySort algo = new MergeSortNonRecursive(array);
        MySort algo = new QuickSort(array);
        algo.printArray("original:",array);
        algo.sort();
        algo.printArray("after:",array);
    }

}



快速排序

public class QuickSort extends MySort {

    public QuickSort(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        quickSort(array, 0, array.length - 1);
    }

    private void quickSort(int[] array, int start, int end) {
        if (array == null || end <= start) {
            return;
        }
        int lastChangePos = splitCompare(array, start, end);
        if (lastChangePos == start) {
            //后面元素都比基准元素大
            quickSort(array, lastChangePos + 1, end);
        } else if (lastChangePos == end) {
            //后面元素都比基准元素小
            quickSort(array, start, lastChangePos - 1);
        } else {
            //基准元素处于中间
            quickSort(array, start, lastChangePos - 1);
            quickSort(array, lastChangePos + 1, end);
        }
    }

    private int splitCompare(int[] array, int start, int end) {
        int quickElement = array[end];

        int exChangePos = start - 1;
        for (int currPos = start; currPos < end; currPos++) {
            if (array[currPos] < quickElement) {
                exChangePos++;//理解这个是关键:指示的是最近的一个小于基准元素值的索引
                if (exChangePos != currPos) {
                    exChangeElement(array, exChangePos, currPos);
                }
            }
        }

        if (exChangePos + 1 != end) {
            exChangeElement(array, exChangePos + 1, end);
        }

        printArray(String.format("after splitCompare:(from %d to %d)", start, end), array);
        return exChangePos + 1;
    }
}


堆排序

public class HeapSort extends MySort {
    public HeapSort(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        if(array == null && array.length <= 1){
            return;
        }

        buildMaxHeap(array);
        printArray("after buildMaxHeap:",array);
        for (int size = array.length - 1; size >=1 ; size--) {
            moveMaxElement(array,0,size);//移走最大值元素
            printArray(size + " after moveMaxElement:",array);
            adjustHeap(array,0,size);//从0号开始
            printArray(size + " after adjustHeap:",array);
        }
    }

    private void buildMaxHeap(int[] array) {
        if(array == null && array.length <= 1){
            return;
        }
        //从最后一个非叶子节点元素开始排序
        for (int adjustIndex = array.length/2 ; adjustIndex >= 0; adjustIndex--) {
            adjustHeap(array,adjustIndex,array.length);
        }
    }

    private void moveMaxElement(int[] array, int fisrtIndex, int lastIndex) {
        exChangeElement(array,fisrtIndex,lastIndex);
    }

    private void adjustHeap(int[] array, int adjustIndex, int heapSize) {
        int largest = adjustIndex;
        int left = adjustIndex * 2 + 1;//左子元素不一定存在
        int right = adjustIndex * 2 + 2;//右子元素不一定存在
        if(left < heapSize && array[left] > array[largest]){
            largest = left;
        }
        if(right < heapSize && array[right] > array[largest]){
            largest = right;
        }
        if(largest != adjustIndex){
            exChangeElement(array,adjustIndex,largest);//父子交换
            adjustHeap(array,largest,heapSize);//递归的建立大顶堆
        }
    }

}

插入排序

public class InsertSort extends MySort {

    public InsertSort(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        for (int cur = 0; cur < array.length; cur++) {
            insertSortedArray(array,cur,array[cur]);
        }
    }

    private void insertSortedArray(int[] array, int sortedSize, int value) {
        if(sortedSize == 0){
            array[0] = value;
        }else{
            int cur = sortedSize - 1;
            while(cur >= 0 && array[cur] > value){
                array[cur+1] = array[cur];
                cur--;
            }
            array[cur+1] = value;
        }
    }
}


归并排序

public class MergeSort extends MySort {

    public MergeSort(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        mergeSort(array, 0, array.length - 1);
    }

    private void mergeSort(int[] array, int low, int high) {
        int mid = (low + high) / 2;
        if (low < high) {
            mergeSort(array, low, mid);//左侧继续merge排序
            mergeSort(array, mid + 1, high);//右侧继续merge排序
            merge(array, low, mid, high);//左右侧整合,这个是核心
        }
    }

    private void merge(int[] array, int low, int mid, int high) {
        int[] temp = new int[high - low + 1];
        int leftIndex = low;
        int rightIndex = mid + 1;
        int tempIndex = 0;
        while (leftIndex <= mid && rightIndex <= high) {
            if (array[leftIndex] < array[rightIndex]) {
                temp[tempIndex++] = array[leftIndex++];
            } else {
                temp[tempIndex++] = array[rightIndex++];
            }
        }

        //左侧有多余的
        while (leftIndex <= mid) {
            temp[tempIndex++] = array[leftIndex++];
        }

        //右侧有多余的
        while (rightIndex <= high) {
            temp[tempIndex++] = array[rightIndex++];
        }

        //将临时排序好的何如到原来的数组当中
        for (int i = 0; i < temp.length; i++) {
            array[low + i] = temp[i];
        }
    }
}


非递归的归并排序

public class MergeSortNonRecursive extends MySort {

    public MergeSortNonRecursive(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        nrMergeSort(array, array.length);
    }

    private void nrMergeSort(int[] array, int size) {
        //直接申请n长度的数组空间
        int[] temp = new int[size];

        int stepLength = 1;
        //以2的次幂为步长进行归并排序
        while (stepLength < size) {
            //每次合并到temp中时,都需要会写到array中,然后进行下一轮的合并
            mergeSort(array, temp, stepLength, size);
            stepLength *= 2;
        }
    }


    //循环建立以2*stepLength为长度的子数组进行归并排序
    private void mergeSort(int[] array, int[] temp, int stepLength, int size) {
        final int SUB_ARRAY_SIZE = 2 * stepLength;
        int i = 0;
        while (i + SUB_ARRAY_SIZE <= size - 1) {
            int subArrayBegin = i;
            int subArrayMiddle = i + stepLength - 1;
            int subArrayEnd = i + 2 * stepLength - 1;
            merge(array, temp, subArrayBegin, subArrayMiddle, subArrayEnd);
            i += SUB_ARRAY_SIZE;
        }
        //剩下的元素长度大于一个stepLength,但是小于2*stepLength,还需要进行一次归并
        if (size - i + 1 > stepLength) {
            merge(array, temp, i, i + stepLength - 1, size - 1);
        }else{
            //剩下的元素不足一个stepLength
            for (int j = i; j < size; j++) {
                temp[j] = array[j];
            }
        }

        //回写到原来的数组当中
        for (int s = 0; s < size; s++) {
            array[s] = temp[s];
        }
    }

    //核心:merge一段子数组
    private void merge(int[] array, int[] temp, int begin, int mid, int end) {
        int array1Index = begin;
        int array2Index = mid + 1;
        int pos;
        for (pos = array1Index; array1Index <= mid && array2Index <= end; pos++) {
            if(array[array1Index] < array[array2Index]){
                temp[pos] = array[array1Index++];
            }else{
                temp[pos] = array[array2Index++];
            }
        }
        if(array1Index <= mid){
            for (int h = 0; h <= mid - array1Index; h++) {
                temp[pos + h] = array[array1Index + h];
            }
        }else{
            for (int h = 0; h <= end - array2Index; h++) {
                temp[pos + h] = array[array2Index + h];
            }
        }
    }
}

冒泡排序

public class BubbleSort extends MySort {
    public BubbleSort(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        for (int cur = 0; cur < array.length - 1; cur++) {
            for (int next = 0; next < array.length - 1 - cur; next++) {
                if(array[next] > array[next+1]){
                    exChangeElement(array,next,next+1);
                }
            }
        }
    }
}

public class MarkedBubbleSort extends MySort {
    public MarkedBubbleSort(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        //设置一个标志位,记录上次交换的位置,后面的为交换的元素则代表了已经排序好了
        int lastExchangePos = array.length - 1;
        for (int cur = 0; cur < array.length - 1; cur++) {

            int exChangePos = lastExchangePos;
            for (int next = 0; next < lastExchangePos; next++) {
                if(array[next] > array[next+1]){
                    exChangeElement(array,next,next+1);
                    exChangePos = next;
                }
            }

            lastExchangePos = exChangePos;
        }
    }
}

public class MaxMinBubbleSort extends MySort {
    public MaxMinBubbleSort(int[] array) {
        super(array);
    }

    @Override
    public void sort() {
        int low = 0;
        int high = array.length - 1;
        while (low < high) {
            for (int j = low; j < high; j++) {//正向冒泡
                if (array[j] > array[j + 1]) {
                    exChangeElement(array, j, j + 1);
                }
            }
            --high;
            for (int j = high; j > low; j--) {//反向冒泡
                if (array[j] < array[j - 1]) {
                    exChangeElement(array, j, j - 1);
                }
            }
            ++low;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值