幾個常見的算法

 遞歸算法:本身調用本身java

          1.計算乘法1*2..... (n-1)*n的積算法

         public static int getReult(int num){shell

                   if(num==0){數組

                            return 0;ide

                   }函數

                   if(num==1){測試

                            return 1;ui

                   }this

                   return num*getReult(num-1);spa

         }

         2.100之內的階乘

          public static BigInteger sum(int i) { 

                 if (i == 1) {   return BigInteger.ONE;  } 

                 return BigInteger.valueOf(i).multiply(sum(i-1)); 

           } 

        

         /**

          * 計算從1+...num 的和

          * 10000之內

          * @param num

          * @return

          */

         public static int getSumReult(int num){

                   if(num==0){

                            return 0;

                   }

                   if(num==1){

                            return 1;

                   }

                   return num+getSumReult(num-1);

         }

 

/***

    * 二分法查找:二分查找 二分查找也稱折半查找(Binary

    * Search),它是一種效率較高的查找方法。可是,折半查找要求線性表必須採用順序存儲結構,

    * 並且表中元素按關鍵字有序排列。

    */

   public static int findTag(int a[], int tag) {

      int start=0;

       int end=a.length;

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

         int mid=(start+end)/2;

        if(tag==a[mid]){

           return mid;

        }

        if(tag>a[mid]){

           start=mid+1;

        }

        if(tag<a[mid]){

           end=mid-1;

        }

      }

      return -1;//沒有找到

   }

 

 

/**

    * 選擇排序

    * @param numbers

    * @return

    */

   public static int[] selectSortNew(int[] numbers){

      int  tempData;

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

         int k = i;////假設k的下標的值最小

         for (int j = numbers.length-1; j >i; j--){

            if (numbers[k] > numbers[j]){

               k = j;

            }

         }

          tempData = numbers[i];

          numbers[i]=numbers[k];

          numbers[k]=tempData;

      }

      return numbers;

   }

  

   public static void main(String[] args) {

      int a[] = { 21,35,56,57,90,78,101};

      int b[] = selectSortNew(a);

      System.out.println(Arrays.toString(b));

     

   }

 

     /**

     * 快速排序

     * @param numbers

     * @param start

     * @param end

     * @return

     */

   public static int[]  quickSortNew(int[] numbers, int start, int end) {  

       if (start < end) {  

           int base = numbers[start]; // 選定的基準值(第一個數值做爲基準值)  

           int temp; // 記錄臨時中間值  

           int i = start, j = end;  

           do {  

               while ((numbers[i] < base) && (i < end))  

                   i++;  

               while ((numbers[j] > base) && (j > start))  

                   j--;  

               if (i <= j) {  

                   temp = numbers[i];  

                   numbers[i] = numbers[j];  

                   numbers[j] = temp;  

                   i++;  

                   j--;  

               }  

           } while (i <= j);  

          

           if (start < j)  

             quickSortNew(numbers, start, j);  

          

           if (end > i)  

             quickSortNew(numbers, i, end); 

       }  

       return numbers;

   }

  

   public static void main(String[] args) {

      int a[] = { 21,35,56,57,90,78,101};

      int b[] = quickSortNew(a,0,6);

      System.out.println(Arrays.toString(b));

     

   }

 

 

       // 冒泡排序算法 效率低

      public static int[] BubbleSortInt(int[] array) {

 

        int temp;

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

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

              if (array[j - 1] > array[j]) {

                 // 若是前面一個數大於後面一個數則交換

                 temp = array[j - 1];

                 array[j - 1] = array[j];

                 array[j] = temp;

              }

           }

 

        }

 

        return array;

      }

     

      public static void main(String[] args) {

        int a[] = { 21,35,56,57,90,78,101};

        int b[] = BubbleSortInt(a);

        System.out.println(Arrays.toString(b));

      }

}

 

/*

       * 直接插入排序 一、首先比較數組的前兩個數據,並排序;

       * 二、比較第三個元素與前兩個排好序的數據,並將第三個元素放入適當的位置;

       * 三、比較第四個元素與前三個排好序的數據,並將第四個元素放入適當的位置;

       * 四、直至把最後一個元素放入適當的位置。

       * 直接插入排序是穩定的。直接插入排序的平均時間複雜度爲O(n2)。

       */

      public static int[]  sortChaRu(int[] arr) {

           int tmp;

          //無須序列

           for(int i = 1; i < arr.length; i++) {

               // 待插入數據

               tmp = arr[i];

               int j;

              

               //有序序列

               for(j = i - 1; j >= 0; j--) {

                   // 判斷是否大於tmp,大於則後移一位

                   if(arr[j] > tmp) {

                       arr[j+1] = arr[j];

                   }else{

                       break;

                   }

               }

               arr[j+1] = tmp;

           }

           return arr;

       }

     

      public static void main(String[] args) {

        int a[] = { 21,35,56,57,90,78,101};

        int b[] = sortChaRu(a);

        System.out.println(Arrays.toString(b));

      }

 

 

 

String數組中取出相同的字符串

          把數組A的數據做爲map的key和value, 而後用B的數據取值,不爲NULL,說明相同Map接口 Map提供了一種映射關係,其中的元素是以鍵值對(key-value)的形式存儲的,可以實現根據key快速查找value;Map中的鍵值對以Entry類型的對象實例形式存在;建(key值)不可重複,value值能夠重複,一個value值能夠和不少key值造成對應關係,每一個建最多隻能映射到一個值。

Map支持泛型,形式如:Map<K,V> Map中使用put(K key,V value)方法添加, HashMap類 HashMap是Map的一個重要實現類,也是最經常使用的,基於哈希表實現 HashMap中的Entry對象是無序排列的

Key值和value值均可覺得null,可是一個HashMap只能有一個key值爲null的映射(key值不可重複)

         public static List<String> getSameElementByMap(String[] strArr1, String[] strArr2) {

                   // HashMap key值 不可重複 Key值和value值均可覺得null

                   HashMap<String, Object> map = new HashMap<String, Object>();

                   // 數組A中的元素放入Map中

                   for (String string1 : strArr1) {

                            map.put(string1, string1);

                   }

                   List<String> list = new ArrayList<String>();

                   // 用數組B元素作爲Key來取值,如爲NULL則說明相同

                   for (String string2 : strArr2) {

                            Object j = map.get(string2);

                            if (j != null) {

                                     list.add(string2);

                                     // System.out.println("數組AB中相同的元素: "+j.toString());

                            }    }

                   return list;

         }

測試例子:

public static void main(String[] args) {             

String[] strArr1 = { "21002023","21002030","21002225","21002389","21002393","21002396"};

String[] strArr2 = { "21002023","21002030","21002225","21002389","21002393","21002396",

                                     "21002012","21002222","21002407"};

                   System.out.println(getSameElementByMap(strArr1, strArr2).toString());

                   int res1=getReult(12);

                   System.out.println(res1);

                  

                   BigInteger res=sum(12);

                   System.out.println(res);

 

                   int sun=getSumReult(10000);

                   System.out.println(sun);

         }

}

 

 

 兩個大於1000的數的乘積

 public class NumDividEqual {

 

             public char[] A;

             public char[] B;

             int n;

             /**

              * 將數組均分爲兩份,分別存入數組A和數組B中;

              * @param input

              */

             public NumDividEqual(char[] input){

                 n = input.length/2;

                 A = new char[n];

                 B = new char[n];

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

                     A[i] = input[i];

                 }

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

                     B[i] = input[i + n];

                 }     

             }

          

             public static void main(String[] args) {

                 // TODO Auto-generated method stub

             }

}

package com.hyhl.test;

import java.util.Arrays;

public class BigIntMult {

        

          /**

     * 將字符數組倒序排列

     * @param input

     * @return

     */

    public char[] reverse(char[] input) {

        char[] output = new char[input.length];

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

            output[i] = input[input.length - 1 - i];

        }

        return output;

    }

   

    /**

     * 將大整數平均分紅兩部分

     * @param input

     * @return

     */

    public NumDividEqual partition(char[] input) {

        return new NumDividEqual(input);

    }

 

    /**

     * 求兩數組中較大數組的長度,若是其長度爲奇數則+1變偶

     * @param num1

     * @param num2

     * @return

     */

    public int calLength(char[] num1, char[] num2) {

        int len = num1.length > num2.length ? num1.length : num2.length;

        if (len == 1)

            return 1;

        len += len & 1;

        return len;

    }

 

    /**

     * 除去數字前面多餘的0

     * @param input

     * @return

     */

    public static char[] trimPrefix(char[] input) {

        char[] ret = null;

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

            if (ret == null && input[i] == '0')

                continue;

            else {

                if (ret == null) {

                    ret = new char[input.length - i];//出去數字前面多餘的0

                }

                ret[i - (input.length - ret.length)] = input[i];

            }

        }

        if (ret == null)

            return new char[] { '0' };

        return ret;

    }

   

    /**

     * 數組若是長度不足n,則在數組前面補0,使長度爲n。

     * @param input 輸入數組要求數字的最高位存放在數組下標最小位置

     * @param n

     * @return

     */

    public static char[] format(char[] input, int n) {//;

        if (input.length >= n) {

            return input;

        }

        char[] ret = new char[n];

        for (int i = 0; i < n - input.length; i++) {

            ret[i] = '0';

        }

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

            ret[n - input.length + i] = input[i];

        }

        return ret;

    }

 

    /**

     * 大整數尾部補0。至關於移位,擴大倍數

     * @param input

     * @param n

     * @return

     */

    public char[] addTail(char[] input, int n) {//

        char[] ret = new char[input.length + n];

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

            ret[i] = input[i];

        }

        for (int i = input.length; i < ret.length; i++) {

            ret[i] = '0';

        }

        return ret;

    }

   

    /**

     * 大整數加法

     * @param num1

     * @param num2

     * @return

     */

    public char[] add(char[] num1, char[] num2) {

        int len = num2.length > num1.length ? num2.length : num1.length;

        int carry = 0;//進位標識

        num1 = format(num1, len);

        num2 = format(num2, len);

        char[] ret = new char[len + 1];

 

        for (int i = len - 1; i >= 0; i--) {

            int tmp = num1[i] + num2[i] - 96;

            tmp += carry;

            if (tmp >= 10) {

                carry = 1;

                tmp = tmp - 10;

            } else {

                carry = 0;

            }

            ret[len - i - 1] = (char) (tmp + 48);

        }

        ret[len] = (char) (carry + 48);//最後一次,最高位的進位

        return trimPrefix(reverse(ret));

    }

    /**

     * 大整數減法:

     * @param num1 被減數,大整數乘法中只有一個減法(A+B)(C+D)-(AC+BD)=AC+BC>0,所以參數num1>num2且都爲正

     * @param num2 減數

     * @return

     */

    public static char[] sub(char[] num1, char[] num2) {

        int lenMax = num1.length > num2.length ? num1.length : num2.length;

        char[] newNum1 = Arrays.copyOf(format(num1, lenMax), lenMax);//字符串前面補0,使兩串長度相同

        char[] newNum2 = Arrays.copyOf(format(num2, lenMax), lenMax);

       

        for(int i=0;i<lenMax;i++){//when num1-num2<0 return

            if((newNum1[i]=='0' && newNum1[i]=='0') || newNum1[i] == newNum2[i]){//newNum1 is bigger; 

                continue;

            }

            else if(newNum1[i] < newNum2[i]){//不滿足參數num1>num2;

                    System.out.println("The Parameter in sub(A,B).A MUST Bigger Than B!");

                    System.exit(0);

                 }

            else break;

        }

 

        for(int i=lenMax-1;i>=0;i--){

            if(newNum1[i] < newNum2[i]){//result < 0

             newNum1[i] = (char) (newNum1[i] + '0' + 10 - newNum2[i]);

             newNum1[i-1] = (char) (newNum1[i-1] - 1);

            }

            else{

                newNum1[i] = (char) (newNum1[i] + '0' - newNum2[i]);

            }

        }

        return trimPrefix(newNum1);

    }     

    /**

     * 大整數乘法

     * @param num1

     * @param num2

     * @return

     */

    public char[] mult(char[] num1, char[] num2) {

        char[] A, B, C, D, AC, BD, AjB, CjD, ACjBD, AjBcCjD,  SUM;

        int N = calLength(num1, num2);//求兩數組中較大數組的長度,若是長度爲奇數則+1變偶,方便二分紅兩部分

        num1 = format(num1, N);//數組高位存整數的高位數;數字前面補0,使長度爲n;

        num2 = format(num2, N);

        if (num1.length > 1) {

            NumDividEqual nu1 = partition(num1);//將大整數平均分紅兩部分

            NumDividEqual nu2 = partition(num2);

            A = nu1.A;

            B = nu1.B;

            C = nu2.A;

            D = nu2.B;

            AC = mult(A, C);//分治求大整數乘法

            BD = mult(B, D);

            AjB = add(A,B);

            CjD = add(C,D);

            ACjBD = add(AC,BD);

            AjBcCjD = mult(AjB, CjD);

           

            char[] tmp1 = addTail(sub(AjBcCjD, ACjBD), N / 2);//尾部補0,至關於移位

            char[] tmp2 = add(addTail(AC, N), BD);

            SUM = add(tmp1, tmp2);

            char[] test = trimPrefix(SUM);//除去結果前面多餘的0

            return test;

        } else {

            Integer ret = (num1[0] - 48) * (num2[0] - 48);

            return ret.toString().toCharArray();

        }

    }

   

 

    public static void main(String[] args) {

        String st1 = "16874631564134797979843343322342245222344533334432223345224432212";

        String st2 = "1646816547674468877974513161584444444221333498800000998898383818191292098887773999919";

        char[] a = st1.toCharArray();

        char[] b = st2.toCharArray();

        BigIntMult bg = new BigIntMult();

       

        //大整數乘法

        char[] ret = bg.mult(a, b);

       

        System.out.println(ret);

    }

}

 

 

算法:

插入排序的時間複雜度爲:O(N^2)

希爾排序的時間複雜度爲:平均爲:O(N^3/2)    最壞: O(N^2)

歸併排序時間複雜度爲: O(NlogN)   空間複雜度爲:  O(N)

1.堆排序

public int[] heapSort(int[] array) {

                   // 初始建堆,array[0]爲第一趟值最大的元素

                   array = buildMaxHeap(array);

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

                            // 將堆頂元素和堆低元素交換,即獲得當前最大元素正確的排序位置

                            int temp = array[0];

                            array[0] = array[i];

                            array[i] = temp;

                            // 整理,將剩餘的元素整理成堆

                            adjustDownToUp(array, 0, i);

                   }

                   return array;

         }

 

         // 構建大根堆:將array當作徹底二叉樹的順序存儲結構

         private int[] buildMaxHeap(int[] array) {

                   // 從最後一個節點array.length-1的父節點(array.length-1-1)/2開始,直到根節點0,反覆調整堆

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

                            adjustDownToUp(array, i, array.length);

                   }

                   return array;

         }

 

         // 將元素array[k]自下往上逐步調整樹形結構

         private void adjustDownToUp(int[] array, int k, int length) {

                   int temp = array[k];

                   for (int i = 2 * k + 1; i < length - 1; i = 2 * i + 1) { // i爲初始化爲節點k的左孩子,沿節點較大的子節點向下調整

                            if (i < length && array[i] < array[i + 1]) { // 取節點較大的子節點的下標

                                     i++; // 若是節點的右孩子>左孩子,則取右孩子節點的下標

                            }

                            if (temp >= array[i]) { // 根節點 >=左右子女中關鍵字較大者,調整結束

                                     break;

                            } else { // 根節點 <左右子女中關鍵字較大者

                                     array[k] = array[i]; // 將左右子結點中較大值array[i]調整到雙親節點上

                                     k = i; // 【關鍵】修改k值,以便繼續向下調整

                            }

                   }

                   array[k] = temp; // 被調整的結點的值放人最終位置

         }

       

6.希爾排序

 希爾排序(縮小增量法)屬於插入類排序,由Shell提出,希爾排序對直接插入排序進行了簡單的改進:它經過加大插入排序中元素之間的間隔,並在這些有間隔的元素中進行插入排序, 從而使數據項大跨度地移動,當這些數據項排過一趟序以後,希爾排序算法減少數據項的間隔再進行排序,依次進行下去, 進行這些排序時的數據項之間的間隔被稱爲增量,習慣上用字母h來表示這個增量。

經常使用的h序列由Knuth提出,該序列從1開始,經過以下公式產生: h = 3 * h +1反過來程序須要反向計算h序列,應該使用h=(h-1)/3

          */

         public static int[] shellSort(int[] data) {

                   // 計算出最大的h值

                   int h = 1;

                   while (h <= data.length / 3) {

                            h = h * 3 + 1;

                   }

                   while (h > 0) {

                            for (int i = h; i < data.length; i += h) {

                                     if (data[i] < data[i - h]) {

                                               int tmp = data[i];

                                               int j = i - h;

                                               while (j >= 0 && data[j] > tmp) {

                                                        data[j + h] = data[j];

                                                        j -= h;

                                               }

                                               data[j + h] = tmp;

                                     }

                            }

                            // 計算出下一個h值

                            h = (h - 1) / 3;

                   }

                   return data;

         }

  1. 7.   /**    

          * 歸併排序 分而治之(divide - conquer);

          *  每一個遞歸過程涉及三個步驟

          *  第一, 分解: 把待排序的 n 個元素的序列分解成兩個子序列,每一個子序列包括 n/2 個元素.

          *  第二, 治理: 對每一個子序列分別調用歸併排序MergeSort, 進行遞歸操做

          *  第三, 合併: 合併兩個排好序的子序列,生成排序結果.

          * (1)穩定性 歸併排序是一種穩定的排序。

          * (2)存儲結構要求 可用順序存儲結構。也易於在鏈表上實現。

          * (3)時間複雜度對長度爲n的文件,需進行趟二路歸併,每趟歸併的時間爲O(n),故其時間複雜度不管是在最好狀況下仍是在最壞狀況下均是O(nlgn)。

          * (4)空間複雜度 須要一個輔助向量來暫存兩有序子文件歸併的結果,故其輔助空間複雜度爲O(n),顯然它不是就地排序

          * 注意:若用單鏈表作存儲結構,很容易給出就地的歸併排序

          */

         public static int[] mergeSort(int[] a, int low, int high) {

                   int mid = (low + high) / 2;

                   if (low < high) {

                            mergeSort(a, low, mid);

                            mergeSort(a, mid + 1, high);

                            // 左右歸併

                            merge(a, low, mid, high);

                   }

                   return a;

         }

 

         public static void merge(int[] a, int low, int mid, int high) {

                   int[] temp = new int[high - low + 1];

                   int i = low;

                   int j = mid + 1;

                   int k = 0;

                   // 把較小的數先移到新數組中

                   while (i <= mid && j <= high) {

                            if (a[i] < a[j]) {

                                     temp[k++] = a[i++];

                            } else {

                                     temp[k++] = a[j++];

                            }

                   }

                   // 把左邊剩餘的數移入數組

                   while (i <= mid) {

                            temp[k++] = a[i++];

                   }

                   // 把右邊邊剩餘的數移入數組

                   while (j <= high) {

                            temp[k++] = a[j++];

                   }

                   // 把新數組中的數覆蓋nums數組

                   for (int x = 0; x < temp.length; x++) {

                            a[x + low] = temp[x];

                   }

         }

------------------------5種查找------------------------------------------------------------------

線性查找分爲:順序查找、折半查找。

查找有兩種形態:

分爲:破壞性查找,好比有一羣mm,我猜她們的年齡,第一位猜到了是23+,此時這位mm已經從我腦海裏面的mmlist中remove掉了。哥不找23+的,因此此種查找破壞了原來的結構。非破壞性查找, 這種就反之了,不破壞結構。

 

順序查找:這種很是簡單,就是過一下數組,一個一個的比,找到爲止。

 1   // 順序查找

         public static int SequenceSearch(int[] array, int key) {

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

                            // 查找成功,返回序列號

                            if (key == array[i])

                                     return i;

                   }

                   // 未能查找,返回-1

                   return -1;

         }

2. 折半查找 長度必須是奇數

          第一: 數組必須有序,不是有序就必須讓其有序,你們也知道最快的排序也是NLogN

          第二: 這種查找只限於線性的順序存儲結構。

         public static int BinarySearchNew(int[] array, int tag) {

                   int frist = 0;

                   int end = array.length;

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

                            int middle = (frist + end) / 2;

 

                            if (tag == array[middle]) {

                                     // 正好相等 則返回查詢結果

                                     return middle;

                            }

                            if (tag > array[middle]) {

                                     // 大於 middle

                                     frist = middle + 1;

                            }

                            if (tag < array[middle]) {

                                     // 下於 middle

                                     end = middle - 1;

                            }

                  }

                   return -1;

         }

線性查找時間複雜度:O(n);

折半無序(用快排活堆排)的時間複雜度:O(NlogN)+O(logN);

折半有序的時間複雜度:O(logN);

 

3其實經常使用的作哈希的手法有「五種」

第一種:」直接定址法「:很容易理解,key=Value+C; 這個「C"是常量。Value+C其實就是一個簡單的哈希函數。

第二種:「除法取餘法」: 很容易理解, key=value%C;解釋同上。

第三種:「數字分析法」:好比有一組value1=112233,value2=112633,value3=119033, 針對這樣的數咱們分析數中間兩個數比較波動,其餘數不變。那麼咱們取key的值就能夠是key1=22,key2=26,key3=90。

第四種:「平方取中法」。

第五種:「摺疊法」:好比value=135790,要求key是2位數的散列值。那麼咱們將value變爲13+57+90=160, 而後去掉高位「1」,此時key=60,哈哈,這就是他們的哈希關係,這樣作的目的就是key與每一位value都相關,來作到「散列地址」儘量分散的目地。

 

解決衝突經常使用的手法也就2種:

第一種:開放地址法。

   所謂」開放地址「,其實就是數組中未使用的地址。也就是說,在發生衝突的地方,後到的那個元素(可採用兩種方式:①線性探測,②函數探測)向數組後尋找"開放地址「而後把本身插進入。

第二種:連接法。原理就是在每一個元素上放一個」指針域「,在發生衝突的地方,後到的那個元素將本身的數據域拋給衝突中的元素,此時衝突的地方就造成了一個鏈表。

設計函數採用:除法取餘法。

 衝突方面採用:開放地址線性探測法。

          

5二叉排序樹查找

1. 概念:

<1> 其實很簡單,若根節點有左子樹,則左子樹的全部節點都比根節點小。若根節點有右子樹,則右子樹的全部節點都比根節點大。

    <2> 如圖就是一個」二叉排序樹「,而後對照概念一比較比較

/**

 * 二叉排序樹

 * 採用廣度優先法則來遍歷排序二叉樹獲得的不是有序序列,

 * 採用中序遍從來遍歷排序二叉樹才能夠獲得有序序列。

 *

 */

public class SortedBinTree <T extends Comparable>{

             static class Node {

                 Object data;

                 Node parent;

                 Node left;

                 Node right;

                 public Node(Object data, Node parent, Node left, Node right) {

                     this.data = data;

                     this.parent = parent;

                     this.left = left;

                     this.right = right;

                 }

                 public String toString() {

                     return "[data=" + data + "]";

                 }

                 public boolean equals(Object obj) {

                     if (this == obj) {

                         return true;

                     }

                     if (obj.getClass() == Node.class) {

                         Node target = (Node) obj;

                         return data.equals(target.data) && left == target.left && right == target.right && parent == target.parent;

                     }

                     return false;

                 }

 

             }

 

             private Node root;

 

             // 兩個構造器用於建立排序二叉樹

             public SortedBinTree() {

                 root = null;

             }

 

             public SortedBinTree(T o) {

                 root = new Node(o, null, null, null);

             }

 

             // 添加節點

             public void add(T ele) {

                 // 若是根節點爲null

                 if (root == null) {

                     root = new Node(ele, null, null, null);

                 } else {

                     Node current = root;

                     Node parent = null;

                     int cmp = 0;

                     // 搜索合適的葉子節點,以該葉子節點爲父節點添加新節點

                     do {

                         parent = current;

                         cmp = ele.compareTo(current.data);

                         // 若是新節點的值大於當前節點的值

                         if (cmp > 0) {

                             // 以右子節點做爲當前節點

                             current = current.right;

                         } else {

                             // 若是新節點的值小於當前節點的值

                             // 以左節點做爲當前節點

                             current = current.left;

                         }

                     }

                     while (current != null);

                     // 建立新節點

                     Node newNode = new Node(ele, parent, null, null);

                     // 若是新節點的值大於父節點的值

                     if (cmp > 0) {

                         // 新節點做爲父節點的右子節點

                         parent.right = newNode;

                     } else {

                         // 若是新節點的值小於父節點的值

                         // 新節點做爲父節點的左子節點

                         parent.left = newNode;

                     }

                 }

             }

 

             // 刪除節點

             public void remove(T ele) {

                 // 獲取要刪除的節點

                 Node target = getNode(ele);

                 if (target == null) {

                     return;

                 }

                 // 左、右子樹爲空

                 if (target.left == null && target.right == null) {

                     // 被刪除節點是根節點

                     if (target == root) {

                         root = null;

                     } else {

                         // 被刪除節點是父節點的左子節點

                         if (target == target.parent.left) {

                             // 將target的父節點的left設爲null

                             target.parent.left = null;

                         } else {

                             // 將target的父節點的right設爲null

                             target.parent.right = null;

                         }

                         target.parent = null;

                     }

                 } else if (target.left == null && target.right != null) {

                     // 左子樹爲空,右子樹不爲空

                     // 被刪除節點是根節點

                     if (target == root) {

                         root = target.right;

                     } else {

                         // 被刪除節點是父節點的左子節點

                         if (target == target.parent.left) {

                             // 讓target的父節點的left指向target的右子樹

                             target.parent.left = target.right;

                         } else {

                             // 讓target的父節點的right指向target的右子樹

                             target.parent.right = target.right;

                         }

                         // 讓target的右子樹的parent指向target的parent

                         target.right.parent = target.parent;

                     }

                 } else if (target.left != null && target.right == null) {

                     // 左子樹不爲空,右子樹爲空

                     // 被刪除節點是根節點

                     if (target == root) {

                         root = target.left;

                     } else {

                         // 被刪除節點是父節點的左子節點

                         if (target == target.parent.left) {

                             // 讓target的父節點的left指向target的左子樹

                             target.parent.left = target.left;

                         } else {

                             // 讓target的父節點的right指向target的左子樹

                             target.parent.right = target.left;

                         }

                         // 讓target的左子樹的parent指向target的parent

                         target.left.parent = target.parent;

                     }

                 } else {

                     // 左、右子樹都不爲空

                     // leftMaxNode用於保存target節點的左子樹中值最大的節點

                     Node leftMaxNode = target.left;

                     // 搜索target節點的左子樹中值最大的節點

                     while (leftMaxNode.right != null) {

                         leftMaxNode = leftMaxNode.right;

                     }

                     // 從原來的子樹中刪除leftMaxNode節點

                     leftMaxNode.parent.right = null;

                     // 讓leftMaxNode的parent指向target的parent

                     leftMaxNode.parent = target.parent;

                     // 被刪除節點是父節點的左子節點

                     if (target == target.parent.left) {

                         // 讓target的父節點的left指向leftMaxNode

                         target.parent.left = leftMaxNode;

                     } else {

                         // 讓target的父節點的right指向leftMaxNode

                         target.parent.right = leftMaxNode;

                     }

                     leftMaxNode.left = target.left;

                     leftMaxNode.right = target.right;

                     target.parent = target.left = target.right = null;

                 }

             }

 

             // 根據給定的值搜索節點

             public Node getNode(T ele) {

                 // 從根節點開始搜索

                 Node p = root;

                 while (p != null) {

                     int cmp = ele.compareTo(p.data);

                     // 若是搜索的值小於當前p節點的值

                     if (cmp < 0) {

                         // 向左子樹搜索

                         p = p.left;

                     } else if (cmp > 0) {

                         // 若是搜索的值大於當前p節點的值

                         // 向右子樹搜索

                         p = p.right;

                     } else {

                         return p;

                     }

                 }

                 return null;

             }

 

             // 廣度優先遍歷

             public List<Node> breadthFirst() {

 

                 Queue<Node> queue = new ArrayDeque<Node>();

                 List<Node> list = new ArrayList<Node>();

                 if (root != null) {

                     // 將根元素入「隊列」

                     queue.offer(root);

                 }

                 while (!queue.isEmpty()) {

                     // 將該隊列的「隊尾」的元素添加到List中

                     list.add(queue.peek());

                     Node p = queue.poll();

                     // 若是左子節點不爲null,將它加入「隊列」

                     if (p.left != null) {

                         queue.offer(p.left);

                     }

                     // 若是右子節點不爲null,將它加入「隊列」

                     if (p.right != null) {

                         queue.offer(p.right);

                     }

                 }

                 return list;

             }

 

           

             //二叉排序的查詢

             public static void main(String[] args) {

 

                 SortedBinTree<Integer> tree = new SortedBinTree<Integer>();

 

                 // 添加節點

                 tree.add(5);

                 tree.add(20);

                 tree.add(10);

                 tree.add(3);

                 tree.add(8);

                 tree.add(15);

                 tree.add(30);

 

                 System.out.println(tree.breadthFirst());

                

                 // 刪除節點

                 tree.remove(20);

                

                 System.out.println(tree.breadthFirst());

 

             }

 

         }

值的注意的是:二叉排序樹一樣採用「空間換時間」的作法。

 

忽然發現,二叉排序樹的中序遍歷一樣能夠排序數組,呵呵,不錯!

 

PS:  插入操做:O(LogN)。 刪除操做:O(LogN)。 查找操做:O(LogN)。

相關文章
相關標籤/搜索