二叉排序樹分為靜態查找(find)和動態查找(insert、delete)
二叉搜索樹:一棵二叉樹,可以為空;如果不為空,滿足下列性質:
1.非空左子樹的所有鍵值小於其根結點的鍵值。
2.非空右子樹的所有鍵值大於其根結點的鍵值
3.左右子樹都是二叉搜索樹!!
1)<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPgo8c3Ryb25nPiAgICAvLyC4/NDCtbHHsL3hteO8sMbk1+bPyLXEuN+2yDwvc3Ryb25nPgo8c3Ryb25nPnB1YmxpYyB2b2lkIHVwZGF0ZUhlaWdodCgpIHs8L3N0cm9uZz4KPHN0cm9uZz4gICAgaW50IG5ld0ggPSAwOy8vINDCuN+2yLP1yry7r86qIDAsuN+2yLXI09rX89PS19PK97jftsi80yAxINbQtcS089XfPC9zdHJvbmc+CjxzdHJvbmc+ICAgIGlmIChoYXNMQ2hpbGQoKSk8L3N0cm9uZz4KPHN0cm9uZz4gICAgICAgIG5ld0ggPSBNYXRoLm1heChuZXdILCAxICYjNDM7IGdldExDaGlsZCgpLmdldEhlaWdodCgpKTsvL7e1u9jBvdXf1tC9z7TztcTSu7j2PC9zdHJvbmc+CjxzdHJvbmc+ICAgIGlmIChoYXNSQ2hpbGQoKSk8L3N0cm9uZz4KPHN0cm9uZz4gICAgICAgIG5ld0ggPSBNYXRoLm1heChuZXdILCAxICYjNDM7IGdldFJDaGlsZCgpLmdldEhlaWdodCgpKTs8L3N0cm9uZz4KPHN0cm9uZz4gICAgaWYgKG5ld0ggPT0gaGVpZ2h0KTwvc3Ryb25nPgo8c3Ryb25nPiAgICAgICAgcmV0dXJuOyAvLyC437bIw7vT0Leiyfqx5Luv1PLWsb3Tt7W72Dwvc3Ryb25nPgo8c3Ryb25nPiAgICBoZWlnaHQgPSBuZXdIOyAvLyC38dTyuPzQwrjftsg8L3N0cm9uZz4KPHN0cm9uZz4gICAgaWYgKGhhc1BhcmVudCgpKTwvc3Ryb25nPgo8c3Ryb25nPiAgICAgICAgZ2V0UGFyZW50KCkudXBkYXRlSGVpZ2h0KCk7IC8vILXduem4/NDC1+bPyLXEuN+2yDwvc3Ryb25nPgo8c3Ryb25nPn08L3N0cm9uZz4KPHN0cm9uZz51cGRhdGVIZWlnaHQgKCmjusj0tbHHsL3hteMgdiC1xLqi19O3osn6seS7r6Osvs3Q6NKqyrnTwyB1cGRhdGVIZWlnaHQKICgpt723qLj80MK1scewveG147ywxuTX5s/IveG147XEuN+2yKGjx+vXotLio6zTydPa0ru49r3hteO1xLjftsi3osn6seS7r6Osu+HTsM/stb3G5Nfmz8i94bXjtcS437bIo6zU2tXiwO/O0sPH1MrQ7daxvdO21MjOus694bXj1rTQ0NXi0ruy2df3oaPS8s6q1Nq2/rLmyvfW0MjOus7Su7j2veG147XEuN+2yKOstry1yNPaxuTX89PS19PK97XEuN+2yNbQtPPV37zTIDGjrLb41/PT0tfTyve1xLjftsjWu9Do0qq78cihuMO94bXj1/PT0rqi19O1xLjftsijrNa70OjSqqaoICgxKcqxvOSho7zMtvi00yB2ILP2t6LR2HBhcmVudCDS/dPDxObQ0M/yyc+jrNLAtM64/NDCuPfX5s/IveG147XEuN+2yLy0v8mho8jnufvU2snPyva5/bPM1tCjrLeiz9bEs7j2veG147XEuN+2yMO709C3osn6seS7r6Osy+O3qL/J0tTWsb3T1tXWuaGj19vJz8v5yvajrLWxttTSu7j2veG14yB2ILX308MgdXBkYXRlSGVpZ2h0CiAoKbe9t6jKsaOsyPQgdiC1xLLjyv3OqiBsZXZlbCh2KaOs1PLX7rbg1rvQ6NKquPzQwiBsZXZlbCh2KSYjNDM7MSC49r3hteO1xLjftsijrNLytMvL47eotcTKsbzkuLTU07bIIFQobikKID0gpq8gKGxldmVsKHYpKaGjPC9zdHJvbmc+CjxzdHJvbmc+ICAgIDKjqSA8L3N0cm9uZz4KPHN0cm9uZz4gICAgLy8KILj80MK1scewveG147ywxuTX5s/ItcTX08vvyv08L3N0cm9uZz4KPHN0cm9uZz5wdWJsaWMgdm9pZCB1cGRhdGVTaXplKCkgezwvc3Ryb25nPgo8c3Ryb25nPiAgICBzaXplID0gMTsgLy8KILP1yry7r86qIDEsveG147G+ye08L3N0cm9uZz4KPHN0cm9uZz4gICAgaWYgKGhhc0xDaGlsZCgpKTwvc3Ryb25nPgo8c3Ryb25nPiAgICAgICAgc2l6ZSAmIzQzOz0gZ2V0TENoaWxkKCkuZ2V0U2l6ZSgpOyAvLwogvNPJz9fz19PK97nmxKM8L3N0cm9uZz4KPHN0cm9uZz4gICAgaWYgKGhhc1JDaGlsZCgpKTwvc3Ryb25nPgo8c3Ryb25nPiAgICAgICAgc2l6ZSAmIzQzOz0gZ2V0UkNoaWxkKCkuZ2V0U2l6ZSgpOyAvLwogvNPJz9PS19PK97nmxKM8L3N0cm9uZz4KPHN0cm9uZz4gICAgaWYgKGhhc1BhcmVudCgpKTwvc3Ryb25nPgo8c3Ryb25nPiAgICAgICAgZ2V0UGFyZW50KCkudXBkYXRlU2l6ZSgpOyAvLwogtd256bj80MLX5s/ItcS55sSjPC9zdHJvbmc+CjxzdHJvbmc+fTwvc3Ryb25nPgo8c3Ryb25nPnVwZGF0ZVNpemUKICgpo7rNrNH5yOe5+73hteMgdiC1xLqi19O3osn6seS7r6Os06a4w7j80MK1scewveG149LUvLDG5Nfmz8i1xLnmxKOho9LyzqrU2rb+subK99bQyM66ztK7uPa94bXjtcS55sSjo6y2vLXI09rG5Nfz09LX08r3tcS55sSj1q66zbzTyc+94bXj19TJ7aOstvjX89PS19PK97XEuebEo9a70OjSqrvxyKG4w73htePX89PSuqLX07XEuebEo7y0v8m78bXDo6zWu9Do0qqmqCAoMSnKsbzkoaPS8rTLy+O3qLXEyrG85Li01NO2yCBUKG4pCiA9IKavIChsZXZlbCh2KSmhozxicj4KICAgIDOjqTwvc3Ryb25nPgo8c3Ryb25nPiAKICAgLy8gts+/qtPruLjH17XEudjPtTwvc3Ryb25nPgo8c3Ryb25nPnB1YmxpYwogdm9pZCBzZXZlcigpIHs8L3N0cm9uZz4KPHN0cm9uZz4gCiAgIGlmICghaGFzUGFyZW50KCkpPC9zdHJvbmc+CjxzdHJvbmc+IAogICAgICAgcmV0dXJuOzwvc3Ryb25nPgo8c3Ryb25nPiAKICAgaWYgKGlzTENoaWxkKCkpPC9zdHJvbmc+CjxzdHJvbmc+IAogICAgICAgcGFyZW50LmxDaGlsZCA9IG51bGw7PC9zdHJvbmc+CjxzdHJvbmc+IAogICBlbHNlPC9zdHJvbmc+CjxzdHJvbmc+IAogICAgICAgcGFyZW50LnJDaGlsZCA9IG51bGw7PC9zdHJvbmc+CjxzdHJvbmc+IAogICBwYXJlbnQudXBkYXRlSGVpZ2h0KCk7IC8vILj80MK4uL3hteO8sMbk1+bPyLjftsg8L3N0cm9uZz4KPHN0cm9uZz4gICAgcGFyZW50LnVwZGF0ZVNpemUoKTsgLy8guPzQwri4veG147ywxuTX5s/IuebEoyA8L3N0cm9uZz4KPHN0cm9uZz4gCiAgIHBhcmVudCA9IG51bGw7PC9zdHJvbmc+CjxzdHJvbmc+IH0gPC9zdHJvbmc+CjxzdHJvbmc+c2V2ZXIoKaO6x9C2z73hteMgdiDT67i4veG14yBwINauvOS1xLnYz7Who7jDy+O3qNDo0qrQ3rjEIHYg0+sgcCC1xNa41evT8qOs0OjSqrOjyv3KsbzkoaOz/bTL1q7N4tPJ09ogcCC94bXjtcS6otfTt6LJ+sHLseS7r6Os0vK0y9Do0qq199PDIHVwZGF0ZUhlaWdodAogKCm6zXVwZGF0ZVNpemUgKCnAtLj80MK4uL3hteMgcCC8sMbk1+bPyLXEuN+2yNPruebEo6GjxuTKsbzkuLTU07bIIFQobikKID0gpq8gKGxldmVsKHYpKaGjPGJyPgogICAgNKOpPC9zdHJvbmc+CjxzdHJvbmc+IAogICAvLyDJ6NbDtbHHsL3hteO1xNfzuqLX0yy3tbvY1K3X87qi19M8L3N0cm9uZz4KPHN0cm9uZz5wdWJsaWMKIEJpblRyZWVOb2RlIHNldExDaGlsZChCaW5UcmVlTm9kZSBsYykgezwvc3Ryb25nPgo8c3Ryb25nPiAKICAgQmluVHJlZU5vZGUgb2xkTEMgPSB0aGlzLmxDaGlsZDs8L3N0cm9uZz4KPHN0cm9uZz4gCiAgIGlmIChoYXNMQ2hpbGQoKSkgezwvc3Ryb25nPgo8c3Ryb25nPiAKICAgICAgIGxDaGlsZC5zZXZlcigpOzwvc3Ryb25nPgo8c3Ryb25nPiAKICAgfSAvLyC2z7+qtbHHsNfzuqLX09PrveG147XEudjPtTwvc3Ryb25nPgo8c3Ryb25nPiAKICAgaWYgKGxjICE9IG51bGwpIHs8L3N0cm9uZz4KPHN0cm9uZz4gCiAgICAgICBsYy5zZXZlcigpOyAvLyC2z7+qIGxjINPrxuS4uL3hteO1xLnYz7U8L3N0cm9uZz4KPHN0cm9uZz4gCiAgICAgICB0aGlzLmxDaGlsZCA9IGxjOyAvLyDIt7aouLjX07nYz7U8L3N0cm9uZz4KPHN0cm9uZz4gCiAgICAgICBsYy5wYXJlbnQgPSB0aGlzOzwvc3Ryb25nPgo8c3Ryb25nPiAKICAgICAgIHRoaXMudXBkYXRlSGVpZ2h0KCk7IC8vILj80MK1scewveG147ywxuTX5s/IuN+2yDwvc3Ryb25nPgo8c3Ryb25nPiAKICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpOyAvLyC4/NDCtbHHsL3hteO8sMbk1+bPyLnmxKM8L3N0cm9uZz4KPHN0cm9uZz4gCiAgIH08L3N0cm9uZz4KPHN0cm9uZz4gCiAgIHJldHVybiBvbGRMQzsgLy8gt7W72NSt1/O6otfTPC9zdHJvbmc+CjxzdHJvbmc+fTwvc3Ryb25nPgo8c3Ryb25nPjxicj4KPC9zdHJvbmc+CjxzdHJvbmc+IAogICAvLyDIodPSuqLX0zwvc3Ryb25nPgo8c3Ryb25nPnB1YmxpYwogQmluVHJlZU5vZGUgZ2V0UkNoaWxkKCkgezwvc3Ryb25nPgo8c3Ryb25nPiAKICAgcmV0dXJuIHJDaGlsZDs8L3N0cm9uZz4KPHN0cm9uZz59PC9zdHJvbmc+CjxzdHJvbmc+PGJyPgo8L3N0cm9uZz4KPHN0cm9uZz4gCiAgIC8vIMno1sO1scewveG147XE09K6otfTLLe1u9jUrdPSuqLX0zwvc3Ryb25nPgo8c3Ryb25nPnB1YmxpYwogQmluVHJlZU5vZGUgc2V0UkNoaWxkKEJpblRyZWVOb2RlIHJjKSB7PC9zdHJvbmc+CjxzdHJvbmc+IAogICBCaW5UcmVlTm9kZSBvbGRSQyA9IHRoaXMuckNoaWxkOzwvc3Ryb25nPgo8c3Ryb25nPiAKICAgaWYgKGhhc1JDaGlsZCgpKSB7PC9zdHJvbmc+CjxzdHJvbmc+IAogICAgICAgckNoaWxkLnNldmVyKCk7PC9zdHJvbmc+CjxzdHJvbmc+IAogICB9IC8vILbPv6q1scew09K6otfT0+u94bXjtcS52M+1PC9zdHJvbmc+CjxzdHJvbmc+IAogICBpZiAocmMgIT0gbnVsbCkgezwvc3Ryb25nPgo8c3Ryb25nPiAKICAgICAgIHJjLnNldmVyKCk7IC8vILbPv6ogbGMg0+vG5Li4veG147XEudjPtTwvc3Ryb25nPgo8c3Ryb25nPiAKICAgICAgIHRoaXMuckNoaWxkID0gcmM7IC8vIMi3tqi4uNfTudjPtTwvc3Ryb25nPgo8c3Ryb25nPiAKICAgICAgIHJjLnBhcmVudCA9IHRoaXM7PC9zdHJvbmc+CjxzdHJvbmc+IAogICAgICAgdGhpcy51cGRhdGVIZWlnaHQoKTsgLy8guPzQwrWxx7C94bXjvLDG5Nfmz8i437bIPC9zdHJvbmc+CjxzdHJvbmc+IAogICAgICAgdGhpcy51cGRhdGVTaXplKCk7IC8vILj80MK1scewveG147ywxuTX5s/IuebEozwvc3Ryb25nPgo8c3Ryb25nPiAKICAgfTwvc3Ryb25nPgo8c3Ryb25nPiAKICAgcmV0dXJuIG9sZFJDOyAvLyC3tbvY1K3T0rqi19M8L3N0cm9uZz4KPHN0cm9uZz59PC9zdHJvbmc+CjxzdHJvbmc+c2V0TENoaWxkKGxjKaGiIGdldFJDaGlsZChyYymjusG9uPbL47eotcS5psTcz+C21KOs0ru49srHyejWw73hteMgdiC1xNfzuqLX06Os0ru49srHyejWw73hteMgdiC1xNPSuqLX06Gjwb249svjt6i1xMq1z9bKx8DgJiMyMDI4NDu1xKOs0tQgc2V0TENoaWxkKCnOqsD9y7XD96GjytfPyKOsyOe5+yB2INPQ1/O6otfTIG9sZExDo6zU8tOmtbG199PDIG9sZExDLgogc2V2ZXIoKbbPv6ogdiDT68bk1/O6otfTtcS52M+1oaMKIMbktM6jrCC199PDIGxjLiBzZXZlcigpts+/qsbk0+u4uL3hteO1xLnYz7Who9fuuvOjrL2owaIgdiDT6yBsYyDWrrzktcS4uNfTudjPtaOssqK199PDIHYuCiB1cGRhdGVTaXplICgp0+sgdi51cGRhdGVIZWlnaHQgKCm4/NDCIHYgvLDG5Nfmz8i1xLnmxKPT67jftsihozwvc3Ryb25nPgo8c3Ryb25nPs/Cw+bKx9PDtPrC68q1z9a1xMr3uN+2yLrNsunRr8r30rbX073hteO1xLLZ1/ehozwvc3Ryb25nPgo8c3Ryb25nPjwvc3Ryb25nPjxwcmUgY2xhc3M9"brush:java;">public class BinSearchTreeTest01 {
public Point root;
//訪問結點
public static void visitKey(Point p){
System.out.println(p.getKey() + " ");
}
//構造樹
public static Point Tree(){
Point a = new Point('A', null, null);
Point b = new Point('B', null, a);
Point c = new Point('C', null, null);
Point d = new Point('D', b, c);
Point e = new Point('E', null, null);
Point f = new Point('F', e, null);
Point g = new Point('G', null, f);
Point h = new Point('H', d, g);
return h;// root
}
//求二叉樹的高度 height = max(HL , HR) + 1
public static int height(Point p){
int HL , HR , MaxH;
if(p != null){
HL = height(p.getLeftChild());
HR = height(p.getRightChild());
MaxH = Math.max(HL, HR);
return MaxH + 1;
}
return 0;
}
//求二叉樹的葉子結點
public static void OrderLeaves(Point p){
if(p != null){
if(p.getLeftChild() == null && p.getRightChild() == null)
visitKey(p);
OrderLeaves(p.getLeftChild());
OrderLeaves(p.getRightChild());
}
}
public static void main(String[] args) {
System.out.println("二叉樹的高度為:" + height(Tree()));
System.out.print("二叉樹的葉子結點為:");
OrderLeaves(Tree());
}
}
class Point{
private char key;
private Point LeftChild , RightChild;
public Point(char key , Point LeftChild , Point RightChild){
this.key = key;
this.LeftChild = LeftChild;
this.RightChild = RightChild;
}
public Point(char key){
this(key , null ,null);
}
public char getKey() {
return key;
}
public void setKey(char key) {
this.key = key;
}
public Point getLeftChild() {
return LeftChild;
}
public void setLeftChild(Point leftChild) {
LeftChild = leftChild;
}
public Point getRightChild() {
return RightChild;
}
public void setRightChild(Point rightChild) {
RightChild = rightChild;
}
}
3.下面開始今天的正題,二叉搜索樹的查詢,插入和刪除操作
1)Find
·查找從根結點開始,如果樹為空,返回NULL
·若搜索樹非空,則根結點關鍵字和X進行比較,並進行不同處理:
1)若X小於根結點鍵值,只需要在左子樹進行搜索;
2)若X大於根結點鍵值,在右子樹進行搜索;
3)若兩者比較結果相同,搜索完成,返回此結點。
import java.util.Scanner;
/**
* 二叉搜索樹的操作集錦
*
* @author Administrator
*
*/
class BinSearchTreeTest02 {
public Point1 root;
// 訪問結點
public static void visitKey(Point1 p) {
System.out.println(p.getKey() + " ");
}
// 構造樹
public static Point1 Tree() {
Point1 m = new Point1(4, null, null);
Point1 a = new Point1(6, m, null);
Point1 b = new Point1(5, null, a);
Point1 c = new Point1(14, null, null);
Point1 d = new Point1(10, b, c);
Point1 e = new Point1(24, null, null);
Point1 f = new Point1(25, e, null);
Point1 g = new Point1(20, null, f);
Point1 h = new Point1(15, d, g);
return h;// root
}
// 構造空樹
public static Point1 EmptyTree(int t) {
Point1 a = new Point1(t, null, null);
return a;
}
// *********************************查找操作****************************
/**
* 二叉搜索樹查找操作方法1
*
* @param t
* @param node
* @return
*/
public static boolean contains(int t, Point1 node) {
if (node == null)
return false;// 結點為空,查找失敗
String st = Integer.toString(t);// 把要查找的結點轉化為String類型
int result = compareTo(st, node);
if (result == 1) {
return true;
} else {
return false;
}
}
public static int compareTo(String a, Point1 p) {
// String b = Integer.toString(p.getKey());
// if(a.equals(b))和下面這行是等價的
if (a.equals(p.getKey() + ""))
return 1;
int i = 0, j = 0;
if (p.getLeftChild() != null) {
i = compareTo(a, p.getLeftChild());
}
if (p.getRightChild() != null) {
j = compareTo(a, p.getRightChild());
}
if (i == 1) {
return i;
} else if (j == 1) {
return j;
} else {
return -1;
}
}
/**
* 二叉搜索樹查找操作方法2(遞歸算法) 尾遞歸的方式
*
* @param t
* @param node
* @return
*/
public static Point1 contains2(int t, Point1 node) {
if (node == null)
return null;// 結點為空,查找失敗
if (t > node.getKey())
return contains2(t, node.getRightChild());// 查找右子樹
else if (t < node.getKey())
return contains2(t, node.getLeftChild());// 查找左子樹
else
return node;
}
/**
* 二叉搜索樹查找的搜索方法2的變形,非遞歸算法的效率更高 將尾遞歸改為迭代函數
*
* @param args
*/
public static Point1 contains3(int t, Point1 node) {
while (node != null) {
if (t > node.getKey())
node = node.getRightChild();
else if (t < node.getKey())
node = node.getLeftChild();
else
return node;
}
return null;
}
/**
* 二叉搜索樹的最大元素 根據其性質可以得出二叉搜索樹的最大元一定位於右子樹的最右端,最小元則相反
*
* @param args
*/
public static int findMax(Point1 point) {
if (point != null) {
while (point.getRightChild() != null) {
point = point.getRightChild();
}
}
return point.getKey();
}
public static int findMin(Point1 point) {
if (point == null)
return 0;// 先判斷樹是否為空
else if (point.getLeftChild() == null)
return point.getKey();// 在判斷左子樹是否為空
else
return findMin(point.getLeftChild());
}
public static void main(String[] args, Point1 p) {
System.out.println("此二叉樹的最大結點為:" + findMax(Tree()));
System.out.println("此二叉樹的最小結點為:" + findMin(Tree()));
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
System.out.println("輸入一個結點,將判斷是否是此二叉樹的結點");
int a = scanner.nextInt();
if (contains2(a, Tree()) != null)
System.out.println(a + " 是此二叉樹的結點");
else
System.out.println(a + " 不是此二叉樹的結點");
}
}
class Point1 {
private int key;
private Point1 LeftChild, RightChild;
public Point1(int key, Point1 LeftChild, Point1 RightChild) {
this.key = key;
this.LeftChild = LeftChild;
this.RightChild = RightChild;
}
public Point1(int key) {
this(key, null, null);
}
public int getKey() {
return key;
}
public void setKey(char key) {
this.key = key;
}
public Point1 getLeftChild() {
return LeftChild;
}
public void setLeftChild(Point1 leftChild) {
LeftChild = leftChild;
}
public Point1 getRightChild() {
return RightChild;
}
public void setRightChild(Point1 rightChild) {
RightChild = rightChild;
}
}
(給出了三種不同的查找的思路,不過確實要比另外兩種好實現一些,希望可以有所借鑒,插入和刪除晚些時候放上)