1. 程式人生 > >資料結構Java版的查詢演算法實現

資料結構Java版的查詢演算法實現

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

/**
 * 查詢的基本演算法:
 *                                         - 順下查詢
 *            -基於線性表的查詢(靜態查詢)- 折半查詢
 *            -                            - 分塊查詢
 *            -
 * 比較式查詢 -
 *            -                            - 二叉排序樹(B樹)
 *            -                            - 平衡二叉樹
 *            -基於樹的查詢(動態查詢)
 *            -                            - B- 樹
 *            -                            - B+ 樹
 * 計算式查詢 -  -  - -  -  -              - Hash查詢
 *
 *  2017/8/8.
 */
public class SearchMethod {
    public static void main(String[] agrs){
        int[] num = new int[]{7,9,10,8,2,1,3,4,6,5,20,25,56,0,13,14,15};
//        System.out.println(OrderSearch(num,2));
//        System.out.println(BinarSearch(num,2));
//        int index = BlockSearch(num,SplitBlock(num,3),0);
//        System.out.println(index);
          //構建二叉排序樹
//        BinarySortTree b = new BinarySortTree();
//        b.val = 5;
//        b.left_child = new BinarySortTree();
//        b.right_child = new BinarySortTree();
//        b.left_child.val = 3;
//        b.right_child.val = 7;
//        b.left_child.left_child = new BinarySortTree();
//        b.left_child.right_child = new BinarySortTree();
//        b.left_child.left_child.val = 2;
//        b.left_child.right_child.val = 4;
//        b.right_child.left_child = new BinarySortTree();
//        b.right_child.right_child = new BinarySortTree();
//        b.right_child.left_child.val = 6;
//        b.right_child.right_child.val = 8;
//        SearchMethod search = new SearchMethod();
//        System.out.println(search.BinaryTreeSearch(b,9));


    }

    /** 1
     * 順序查詢:逐個比較,直到找到或者查詢失敗。
     * 時間複雜度可以表示O(h)=O(n)
     * 空間複雜度:S(n) = O(n)
     * @param num 查詢的陣列
     * @param n 查詢的數
     * @return 返回下標
     */
    public static int OrderSearch(int[] num,int n){
        for (int i = 0; i < num.length - 1; i++) {
            if (num[i] == n){
                return i;
            }
        }
        return -1;

    }

    /** 2
     * 二分法查詢:對於已經按照一定順序排列好的列表,
     * 每次都用關鍵字和中間的元素對比,然後判斷是在前部分還是後部分還是就是中間的元素,
     * 然後繼續用關鍵字和中間的元素對比。
     * 時間複雜度可以表示O(h)=O(log2n)
     * @param num 查詢的陣列
     * @param n 查詢的數
     * @return 返回下標
     */
    public static int BinarSearch(int[] num,int n){
        int low = 0;
        int high = num.length - 1;
        while (low <= high){
            int mid = (low+high)/2;
            int tem = num[mid];
            if (tem < n){
                low = mid + 1;
            }else if (tem > n){
                high = mid - 1;
            }else {
                return mid;
            }
        }
        return -1;
    }

    /**
     * 分塊查詢的分塊:0<可分塊<=查詢陣列元素和
     * 採用Hashmap儲存區塊的極值和起始下標
     * @param num 查詢陣列
     * @param n 分塊個數
     * @return 返回分塊起始下標和塊的最大值
     */
    public static HashMap<Integer,Integer> SplitBlock(int[] num,int n){
        HashMap<Integer,Integer> block = new HashMap<>();
        int tem = num[0];
        for (int i = 0; i < num.length - 1; i++) {
            if (i % n == 0){ //起始分塊
                if ((i+n) >= num.length-1){ //判斷是否是最後一個區塊 最後一個區塊元素可能小於或大於前面區塊元素
                    for (int j = i; j < num.length; j++) { //區塊內查詢極值
                        if (num[j] > tem){
                            tem = num[j];
                        }
                    }
                    //儲存區塊極值和起始下標
                    block.put(tem,i);
                }else {
                    for (int j = i; j < i+n; j++) { //區塊內查詢極值
                        if (num[j] > tem){
                            tem = num[j];
                        }
                    }
                    //儲存區塊極值和起始下標
                    block.put(tem,i);
                    //初始化區塊比較值
                    tem = num[i+n-1];
                }
            }
        }
        return block;
    }

    /**
     * 分塊查詢:可查詢任意無排序的陣列
     * step1 先選取各塊中的最大關鍵字構成一個索引表
     * step2 查詢分兩個部分:先對索引表進行二分查詢或 順序查詢,然後在確定的塊中順序查詢。
     * ASLbs=(n/s+s)/2  +1,(其中s是每塊的元素個數,n為表長)
     * 時間複雜度為O(n)~O(log2n)
     * @param num
     * @param index
     * @param n
     * @return
     */
    public static int BlockSearch(int[] num,HashMap<Integer,Integer> index,int n){
        //獲取索引極值進行排序
        Iterator<Integer> ite = index.keySet().iterator();
        int[] index1 = new int[index.size()];
        int i = 0;
        while (ite.hasNext()){
            index1[i++] = ite.next();
        }
        //索引極值從小到大排序
        Arrays.sort(index1);
        //查詢元素所在區塊
        for (int j = 0; j < index1.length; j++) {
            if (n <= index1[j]){ //小於索引值說明在此區塊內進行查詢
                int start = index.get(index1[j]);
                int end = 0;
                if (j != index1.length -1){
                    end = index.get(index1[j+1]);
                }else {
                    end = num.length;
                }
                //查詢區塊元素位置
                for (int k = start; k < end; k++) {
                        if (n == num[k]){
                            return k;
                        }
                }
            }
        }
        return -1;
    }

    /**
     * 二叉排序樹/B樹查詢
     * 時間複雜度:O(logn)
     * @param b 二叉排序樹
     * @param n 查詢值
     * @return 返回結果
     */
   public int BinaryTreeSearch(BinarySortTree b,int n){
       if (b != null){
           if (b.val == n){
               return 1;
           }else if (b.val > n){
               return BinaryTreeSearch(b.left_child,n);
           }else if (b.val < n){
               return BinaryTreeSearch(b.right_child,n);
           }
       }
       return -1;
   }
   //平衡二叉樹:且具有以下性質:它是一 棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。
    //最小二叉平衡樹的節點的公式如下 F(n)=F(n-1)+F(n-2)+1
    //查詢與二叉排序樹一樣
}