經常使用查找和排序

package com.itwang.sort_search;

/**
 * @ProjectName: JavaPractice
 * @Package: com.itwang.sort_search
 * @ClassName: BinarySearch
 * @Author: JikeWang
 * @Description: 二分查找
 * @Date: 2018-08-28 21:21
 * @Version: 1.0
 */
public class Search {

    /**
     * @Method find
     * @Author JikeWang
     * @Version  1.0
     * @Description 順序查找
     * @param array 要查找的元素數組
     * @param key 要查找的元素
     * @Return int 返回查找結果 -1:表示沒有查找到  0~array.length-1: 表示查找到
     * @Exception
     * @Date 2018-08-30 18:42
     */
    public int find(int[] array, int key){
        int i;
        for (i = 0 ;i < array.length; i++){
            if (array[i] == key){
                break;
            }
        }
        if (i == array.length){
            return -1;//若是沒有查找到
        }else{
            return i;//若是查找到
        }
    }
    /**
     * @Method binarySearch
     * @Author JikeWang
     * @Version  1.0
     * @Description 二分查找(折半查找)前提元素必須是有序的
     * @param array 要查找的數組
     * @param key 要查找的關鍵元素
     * @Return int 返回的查找結果,若是找到則返回元素的位置,若是沒有找到則返回元素應該插入的位置
     * @Exception
     * @Date 2018-08-28 21:28
     */
    public int binarySearch(int[] array, int key){
        int low = 0, high = array.length - 1;
        while (low <= high){
            int mid = (high + low) >> 1;
            if (array[mid] < key){
                low = mid + 1;
            }else if (array[mid] > key){
                high = mid - 1;
            }else {
                return mid;
            }
        }
        return low;
    }

    /********************************插入排序********************************/
    /**
     * @Method insertSort
     * @Author JikeWang
     * @Version  1.0
     * @Description 直接插入排序
     * @param array 要排序的數組集合
     * @Return void
     * @Exception
     * @Date 2018-08-30 18:44
     */
    void insertSort(int[] array){
        //直接插入排序,假定前面是有序的,從1後面位置開始插入排序
        System.out.println("---------直接插入排序---------");
        for (int i = 1; i < array.length; i++){
            int tmp = array[i];
            int j = i - 1;
            //遍歷找到插入的位置
            while ((j >= 0) && (tmp < array[j])){
                array[j + 1] = array[j];//若是插入的元素小於當前元素,元素後移
                j--;
            }
            //將要插入的元素插入到找到的位置(j+1)是因爲上面循環結束後減了一次1
            array[j + 1] = tmp;
        }
    }
    /**
     * @Method binaryInsertSort
     * @Author JikeWang
     * @Version  1.0
     * @Description 折半插入排序(跟直接插入排序同樣,只是在查找元素插入位置的時候利用了折半查找
     * @param array 要排序的數組集合
     * @Return void
     * @Exception
     * @Date 2018-08-30 18:45
     */
    void binaryInsertSort(int[] array){
        System.out.println("---------折半插入排序---------");
        for (int i = 1; i < array.length; i++){
            int tmp = array[i];
            int low = binarySearch(array,tmp);
            //元素後移
            for (int j = i - 1; j >= low; j --){
                array[j+1] = array[j];
            }
            array[low] = tmp;
        }
    }
    /**
     * @Method shellSort
     * @Author JikeWang
     * @Version  1.0
     * @Description 希爾排序(先將整個待排序記錄序列分割成若干子序列,分別進行直接插入排序,
     *              待整個序列中的記錄「基本有序」時,再對全體記錄進行一次直接插入排序)
     *              分割序列能夠根據某一增量進行分割
     * @param array
     * @Return void
     * @Exception
     * @Date 2018-08-30 18:49
     */
    public void shellSort(int[] array){
        //增量每次都是/2
        for (int step = array.length / 2; step > 0; step /= 2){
            //從增量那組開始進行插入排序,直至完畢
            for (int i = step; i < array.length; i++){
                int j = i;
                int tmp = array[j];

                //j-step就是表明與它同組隔壁的元素
                while (j - step >= 0 && tmp < array[j - step]){
                    array[j] = array[j - step];
                    j = j - step;
                }
                array[j] = tmp;
            }
        }
    }

    /********************************交換排序********************************/
    /**
     * @Method bubbleSort
     * @Author JikeWang
     * @Version  1.0
     * @Description 冒泡排序,每次循環經過比較相鄰的元素大小進行交換,最終會是最後一個元素時最大的。
     *              第一輪,須要循環n-1次,最後一個元素最大,
     *              第二輪,須要循環n-2次,最後一個元素最大,
     *              以此類推,須要進行n輪,每輪循環n-i次
     * @param array
     * @Return void
     * @Exception
     * @Date 2018-08-30 18:57
     */
    public void bubbleSort(int[] array){
        System.out.println("---------冒泡排序---------");
        //進行array.length次循環,每輪進行array.length - i次循環
        for (int i = 1; i <= array.length; i++){
            boolean flag = true;
            //設定一個標記,若爲true,則表示這次循環
            //沒有進行交換,不然有交換
            for (int j = 0; j < array.length - i; j++){
                if (array[j] > array[j + 1]){
                    swap(array, j, j+1);
                    flag = false;
                }
            }
        }
    }
    /**
     * @Method quickSort
     * @Author JikeWang
     * @Version  1.0
     * @Description 快速排序(快速排序是對冒泡排序的一種改進,經過一趟排序將待排序列分割成獨立的兩部分,
     *              其中一部分記錄的關鍵字均比另外一部分記錄關鍵字小,而後分別對這兩部分記錄進行排序)
     * @param array
     * @param low
     * @param high
     * @Return void
     * @Exception
     * @Date 2018-08-30 19:01
     */
    public void quickSort(int[] array, int low, int high){
        if (low >= high){
            return;
        }
        int index = partition(array, low, high);
        quickSort(array, low, index - 1);
        quickSort(array, index + 1, high);

    }

    public int partition(int[] array, int low, int high) {
        //以第一個元素做爲樞軸值
        int key = array[low];
        while (low < high){
            //從後半部分向前掃描
            while (array[high] >= key && low < high) high--;
            //將後半部分小於樞軸值的元素放到前半部分
            array[low] = array[high];
            //從前半部分向後掃描
            while (array[low] <= key && low < high) low++;
            //將前半部分大於樞軸值的元素放到後半部分
            array[high] = array[low];
        }
        array[low] = key;
        return low;
    }

    /********************************選擇排序********************************/
    /**
     * @Method selectSort
     * @Author JikeWang
     * @Version  1.0
     * @Description 簡單選擇排序(每一次首先選擇當前索引位置的元素是最小值,經過跟後面元素的比較,肯定最小元素位置,
     *              若是最小位置發生變化,則將最小位置的元素賦值到當前選擇的位置)
     * @param array
     * @Return void
     * @Exception
     * @Date 2018-08-30 19:01
     */
    public void selectSort(int[] array){
        System.out.println("---------簡單選擇排序---------");
        for (int i = 0; i < array.length - 1; i++){
            int min = i;
            //每一趟循環比較,找到最小的元素的下標並賦值給min
            for (int j = i + 1;j < array.length; j++){
                if (array[j] < array[min])
                    min = j;
            }
            //若是min發生變化,進行交換
            if (min != i){
                swap(array, min, i);
            }
        }
    }
    //構建大頂堆
    public int[] buildMaxHeap(int[] array){
        for (int i = array.length / 2 - 1;i >= 0;i--){
            //從第一個非葉子節點從下至上,從右至左調整結構
            adjustDownHeap(array, i, array.length);
        }
        return array;
    }
    //向下調整堆
    private void adjustDownHeap(int[] array, int k, int length) {
        //取出當前元素
        int tmp = array[k];
        //i爲初始化爲節點k的左孩子,沿節點較大的子節點向下調整
        for (int i = 2*k + 1; i < length - 1; i = 2*i + 1 ){
            if (i < length && array[i] < array[i+1])//取節點較大的子節點的下標
                i++;//若是節點的右孩子>左孩子,則取右孩子節點的下標
            if (array[i] <= tmp) break;//根節點 >=左右子女中關鍵字較大者,調整結束
            else{ //根節點 <左右子女中關鍵字較大者
                array[k] = array[i];//將左右子結點中較大值array[i]調整到雙親節點上
                k = i; //【關鍵】修改k值,以便繼續向下調整
            }
        }
        array[k] = tmp;//被調整的結點的值放人最終位置
    }
    /**
     * @Method heapSort
     * @Author JikeWang
     * @Version  1.0
     * @Description 堆排序(堆排序首先須要構建堆,這裏是構建大頂堆,構建完畢後須要將元素從小到大整理出來,
     *              由於堆頂元素時最大值,經過從後向前操做,每次將堆頂元素賦值到當前位置,但每次賦值後,
     *               堆的結構就發生了變化,須要從新調整)
     * @param array
     * @Return void
     * @Exception
     * @Date 2018-08-30 19:01
     */
    public void heapSort(int[] array){
        array = buildMaxHeap(array);
        //n-1趟的交換和建堆過程
        for (int i = array.length - 1; i > 1;i--){
            swap(array, 0, i);//將堆頂元素和堆低元素交換
            adjustDownHeap(array, 0, i);//整理、將剩餘的元素整理成堆
        }
    }
    /**
     * @Method deleteMax
     * @Author JikeWang
     * @Version  1.0
     * @Description 刪除堆頂元素操做
     * @param array
     * @Return int[]
     * @Exception
     * @Date 2018-08-30 19:02
     */
    public int[] deleteMax(int[] array){
        //將堆的最後一個元素與堆頂元素交換,堆底元素值設爲-999996
        array[0] = array[array.length-1];
        array[array.length-1] = -99999;
        //對此時的根節點進行向下調整
        adjustDownHeap(array, 0, array.length);
        return array;
    }
    /**
     * @Method insertData
     * @Author JikeWang
     * @Version  1.0
     * @Description 插入操做:向大根堆array中插入數據data
     * @param array
     * @param data
     * @Return int[]
     * @Exception
     * @Date 2018-08-30 19:02
     */
    public int[] insertData(int[] array, int data){
        array[array.length-1] = data; //將新節點放在堆的末端
        int k = array.length-1;  //須要調整的節點
        int parent = (k-1)/2;    //雙親節點
        while(parent >=0 && data>array[parent]){
            array[k] = array[parent];  //雙親節點下調
            k = parent;
            if(parent != 0){
                parent = (parent-1)/2;  //繼續向上比較
            }else{  //根節點已調整完畢,跳出循環
                break;
            }
        }
        array[k] = data;  //將插入的結點放到正確的位置
        return array;
    }

    //兩個位置的元素交換值
    private void swap(int[] array, int j, int i) {
        int tmp = array[j];
        array[j] = array[i];
        array[i] = tmp;
    }
    //打印元素
    void print(int[] array){
        for (int a : array) {
            System.out.print(a + "\t");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        int[] array = {2,5,7,9,24};
        int[] sort_array = {2,5,3,1};
        Search search = new Search();

        //二分查找(折半查找)
        int result = search.binarySearch(array, 10);
        System.out.println(result);

        //直接插入排序
        //search.insertSort(sort_array);

        //折半插入排序
        //search.binaryInsertSort(sort_array);


        //冒泡排序
        //search.binaryInsertSort(sort_array);

        //簡單選擇排序
        //search.selectSort(sort_array);

        //希爾排序
        //search.shellSort(sort_array);

        //快速排序
        //search.quickSort(sort_array, 0, sort_array.length - 1);

        search.heapSort(sort_array);
        search.print(sort_array);

    }
}
相關文章
相關標籤/搜索