import java.util.NoSuchElementException;
import java.util.Stack;
public class BinarySearchTree {
private Node root;
public void put(int item) {
if (root == null) {
root = new Node(item);
} else {
Node node = new Node(item);
Node parent = searchNoChildNode(item);
node.parent = parent;
if (item > parent.item) {
parent.rightChild = node;
} else if (item < parent.item) {
parent.leftChild = node;
}
// System.out.println("node=" + node);
// System.out.println("parent=" + parent);
}
}
/**
* 尋找適合的沒有子節(jié)點(diǎn)的node
*
* @param item
* @return
*/
private Node searchNoChildNode(int item) {
Node node = root;
while (node != null) {
if (item < node.item) {
if (node.leftChild == null)
return node;
node = node.leftChild;
} else {
if (node.rightChild == null)
return node;
node = node.rightChild;
}
}
return node;
}
/**
* 中序:左中右 思路:壓入當(dāng)前節(jié)點(diǎn)连锯,判斷左孩子是否為空住拭, 若為空,則彈出該節(jié)點(diǎn),并打印尸变,并以右孩子為當(dāng)前節(jié)點(diǎn),重復(fù)操作莉兰;
* 若不為空,則以左孩子做當(dāng)前節(jié)點(diǎn)秦效,重復(fù)操作
*
* 重復(fù)操作的意思是呢。涎嚼。阱州。就是壓入堆棧,判斷左孩子是否為空法梯。苔货。。
*/
public void middleOrder() {
Stack<Node> stack = new Stack<>();
Node node = root;
while (node != null || !stack.isEmpty()) {
if (node != null) {
stack.push(node);
node = node.leftChild;
} else {
node = stack.pop();
System.out.print(node.item + " ");
node = node.rightChild;
}
}
System.out.println();
}
/**
* 移除一個(gè)數(shù)
*
* @param data
*/
public void remove(int item) {
Node node = searchNode(item);
System.out.println("刪除節(jié)點(diǎn):" + node);
if (node == null)
throw new NoSuchElementException();// 沒有當(dāng)前節(jié)點(diǎn)
Node parent = node.parent;
if (node.leftChild == null && node.rightChild == null) {// 沒有子節(jié)點(diǎn)立哑,直接刪除就行了
if (parent == null) {// 沒有父節(jié)點(diǎn),說明是root節(jié)點(diǎn)
root = null;// 直接將root置空
} else {
node.parent = null;
if (parent.leftChild == node) {// 如果是父節(jié)點(diǎn)的左子節(jié)點(diǎn)夜惭,則設(shè)置父節(jié)點(diǎn)左子節(jié)點(diǎn)為空
parent.leftChild = null;
} else {// 反之,設(shè)置右子節(jié)點(diǎn)為空
parent.rightChild = null;
}
}
} else if (node.leftChild != null && node.rightChild == null) {// 有左子節(jié)點(diǎn)铛绰,沒有右子節(jié)點(diǎn)
if (parent == null) {// root節(jié)點(diǎn)
root = node.leftChild;// 將root節(jié)點(diǎn)設(shè)置為其左子節(jié)點(diǎn)
} else {
node.parent = null;
if (parent.leftChild == node) {// 如果是父節(jié)點(diǎn)的左子節(jié)點(diǎn)滥嘴,則把自己的左子節(jié)點(diǎn)設(shè)置給父左子節(jié)點(diǎn)
parent.leftChild = node.leftChild;
} else {// 反之,設(shè)置給父右子節(jié)點(diǎn)
parent.rightChild = node.leftChild;
}
node.leftChild.parent = parent;
}
} else if (node.leftChild == null && node.rightChild != null) {// 沒有左子節(jié)點(diǎn)至耻,有右子節(jié)點(diǎn)
if (parent == null) {
root = node.rightChild;
} else {
node.parent = null;
if (parent.leftChild == node) {
parent.leftChild = node.rightChild;
} else {
parent.rightChild = node.rightChild;
}
node.rightChild.parent = parent;
}
} else if (node.leftChild != null && node.rightChild != null) {// 有左子節(jié)點(diǎn)若皱,也有右子節(jié)點(diǎn)
Node mostLeftNode = searchMostLeftNode(node.rightChild);// 搜索右子節(jié)點(diǎn)的最左子節(jié)點(diǎn)
Node mostLeftNodeP = mostLeftNode.parent;// 最左子節(jié)點(diǎn)的父節(jié)點(diǎn)
if (parent == null) {// 是root節(jié)點(diǎn)
root = mostLeftNode;// 將root節(jié)點(diǎn)設(shè)置為右子節(jié)點(diǎn)的最左子節(jié)點(diǎn)
} else {
// 最左子節(jié)點(diǎn)替代刪除節(jié)點(diǎn)
if (parent.leftChild == node) {
parent.leftChild = mostLeftNode;
} else {
parent.rightChild = mostLeftNode;
}
}
// 先處理最左子節(jié)點(diǎn)目前的父節(jié)點(diǎn)和右子節(jié)點(diǎn)的賦值
// 最左子節(jié)點(diǎn)的父節(jié)點(diǎn)的左子節(jié)點(diǎn),設(shè)置為最左子節(jié)點(diǎn)的右子節(jié)點(diǎn)尘颓,因?yàn)樽钭笞庸?jié)點(diǎn)沒有左子節(jié)點(diǎn)
mostLeftNodeP.leftChild = mostLeftNode.rightChild;
if (mostLeftNode.rightChild != null) {
mostLeftNode.rightChild.parent = mostLeftNodeP;
}
// 再給最左子節(jié)點(diǎn)的父節(jié)點(diǎn)和左右子節(jié)點(diǎn)賦上新值
// 最左子節(jié)點(diǎn)替代了了刪除節(jié)點(diǎn)走触,所以其父節(jié)點(diǎn),孩子節(jié)點(diǎn)疤苹,都要等于刪除節(jié)點(diǎn)的父節(jié)點(diǎn)互广,孩子節(jié)點(diǎn)
mostLeftNode.parent = parent;
mostLeftNode.leftChild = node.leftChild;
mostLeftNode.rightChild = node.rightChild;
// 刪除節(jié)點(diǎn)的兩個(gè)子節(jié)點(diǎn)的父節(jié)點(diǎn),也要相應(yīng)的設(shè)置為最左子節(jié)點(diǎn)
node.leftChild.parent = mostLeftNode;
node.rightChild.parent = mostLeftNode;
}
}
/**
* 搜索該節(jié)點(diǎn)的最左子節(jié)點(diǎn)
*
* @param node
* @return
*/
private Node searchMostLeftNode(Node node) {
Node leftNode = node;
while (leftNode != null) {
if (leftNode.leftChild == null)
return leftNode;
leftNode = leftNode.leftChild;
}
return leftNode;
}
/**
* 查詢指定節(jié)點(diǎn)
*
* @param item
* @return
*/
public Node searchNode(int item) {
Node node = root;
while (node != null) {
if (item > node.item) {
node = node.rightChild;
} else if (item < node.item) {
node = node.leftChild;
} else {
return node;
}
}
return null;
}
private class Node {
private int item;
private Node parent;
private Node leftChild;
private Node rightChild;
public Node(int item) {
this.item = item;
}
@Override
public String toString() {
String p = null;
if (parent != null) {
p = String.valueOf(parent.item);
}
String l = null;
if (leftChild != null) {
l = String.valueOf(leftChild.item);
}
String r = null;
if (rightChild != null) {
r = String.valueOf(rightChild.item);
}
return "Node [item=" + item + ", parent=" + p + ", leftChild=" + l + ", rightChild=" + r + "]";
}
}
public static void main(String[] args) {
int[] items = { 20, 31, 10, 12, 54, 23, 11, 5, 100, 43, 26 };
BinarySearchTree tree = new BinarySearchTree();
for (int i : items) {
tree.put(i);
}
System.out.println("初始節(jié)點(diǎn)");
tree.middleOrder();
Node n = tree.searchNode(54);
System.out.println("查找節(jié)點(diǎn):" + n);
tree.remove(20);
tree.middleOrder();
tree.remove(5);
tree.middleOrder();
tree.remove(100);
tree.middleOrder();
tree.remove(43);
tree.middleOrder();
tree.remove(23);
tree.middleOrder();
System.out.println("插入節(jié)點(diǎn):25");
tree.put(25);
tree.middleOrder();
}
}
二叉搜索樹的增刪查
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門友酱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晴音,“玉大人,你說我怎么就攤上這事缔杉〈冈辏” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵或详,是天一觀的道長系羞。 經(jīng)常有香客問我加缘,道長,這世上最難降的妖魔是什么觉啊? 我笑而不...
- 正文 為了忘掉前任,我火速辦了婚禮沈贝,結(jié)果婚禮上杠人,老公的妹妹穿的比我還像新娘。我一直安慰自己宋下,他們只是感情好嗡善,可當(dāng)我...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著学歧,像睡著了一般罩引。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枝笨,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼欺冀!你這毒婦竟也來了树绩?” 一聲冷哼從身側(cè)響起,我...
- 序言:老撾萬榮一對情侶失蹤隐轩,失蹤者是張志新(化名)和其女友劉穎饺饭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體职车,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡砰奕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了提鸟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片军援。...
- 正文 年R本政府宣布空厌,位于F島的核電站庐船,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嘲更。R本人自食惡果不足惜筐钟,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赋朦。 院中可真熱鬧篓冲,春花似錦、人聲如沸宠哄。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽毛嫉。三九已至诽俯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間承粤,已是汗流浹背暴区。 一陣腳步聲響...
- 正文 我出身青樓,卻偏偏與公主長得像浪讳,于是被迫代替她去往敵國和親缰盏。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- BST樹即二叉搜索樹:1.所有非葉子結(jié)點(diǎn)至多擁有兩個(gè)兒子(Left和Right)耐床;2.所有結(jié)點(diǎn)存儲一個(gè)關(guān)鍵字;3....
- 寫在前面 最近在leetcode上做了一些關(guān)于二叉搜索樹(BST)的題目楔脯,仔細(xì)看了下關(guān)于BST的資料撩轰,這兒自己做一...
- 中序遍歷,但是記住要保存前一個(gè)節(jié)點(diǎn)的指針,因此要用到指針的指針作為參數(shù)堪嫂。同時(shí)偎箫,因?yàn)樽詈笠祷仡^指針,不要把返回頭指...
- 到家之后第一次下雪皆串,不大淹办,落地即化,單單余下一圈水印來恶复,其實(shí)更像雨怜森,細(xì)細(xì)的,并不密集寂玲,拿手電一照,亮晶晶的梗摇,卻也能...