程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 漫談二叉搜索樹的基本算法(三種思路實現查詢操作)

漫談二叉搜索樹的基本算法(三種思路實現查詢操作)

編輯:C++入門知識

漫談二叉搜索樹的基本算法(三種思路實現查詢操作)


前面我們說了二叉樹前序中序後序遍歷的遞歸非遞歸算法的實現,下面我們再來說說二叉搜索樹~

二叉排序樹分為靜態查找(find)和動態查找(insert、delete) 二叉搜索樹:一棵二叉樹,可以為空;如果不為空,滿足下列性質: 1.非空左子樹的所有鍵值小於其根結點的鍵值。 2.非空右子樹的所有鍵值大於其根結點的鍵值 3.左右子樹都是二叉搜索樹!! \
2.以上是二叉搜索樹(也叫二叉排序樹)的一些基本操作,此處我們先說一下二叉樹的結點定義·· 代碼中判斷當前結點位置情況的輔助方法以及簡單的 get 方法都在常數時間內可以完成,實現也相應非常簡單。下面主要討論 updateHeight ()、 updateSize ()、 sever()、setLChild(lc)、 getRChild(rc)的實現與時間復雜度。
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;
	}
}

(給出了三種不同的查找的思路,不過確實要比另外兩種好實現一些,希望可以有所借鑒,插入和刪除晚些時候放上)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved