遞歸算法:本身調用本身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;
}
* 歸併排序 分而治之(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)。