1. 程式人生 > >資料結構與演算法總結——二叉查詢樹及其相關操作

資料結構與演算法總結——二叉查詢樹及其相關操作

  • 我實現瞭如下操作

    • 插入,查詢,刪除,最大值
    • 樹的高度,子樹大小
    • 二叉樹的範圍和,範圍搜尋
    • 樹的前序,中序,後序三種遍歷
    • rank
    • 前驅值
  • 在這一版本的程式碼中,我使用了類模板將介面與實現分離,在這之中,遇到了許多問題:

    • 當類模板和實現分別在兩個檔案中實現時,需要直接包含實現檔案而不是模板檔案
    • 實現檔案中,返回類中自定義的資料結構(如結構體)前要加上類名,並且要在前面加入typename關鍵詞,否則會報錯,
      • 如:typename BST<Comparable>::node*
  • 在使用C++實現的時候,也有很多收穫:

    • 對於不改變資料的函式,最好在宣告的最後加上const
      • 不可在宣告為const的函式中使用不是const的函式
      • 在const函式中,所有的成員指標(包括this)都變成的常數指標
    • 使用傳引用操作可以使得insert和delete函式無需返回值
    • 在模板中使用了常引用代替值作為返回值,因為返回引數可能不是基本型別,這麼做可以避免不必要的拷貝
//BST.h

#include <iostream>
using namespace std; template<typename Comparable> class BST { public: struct node { Comparable elements; node* left; node* right; size_t count; node(Comparable Elements, node* Left, node* Right, size_t Count) :elements(Elements), left(Left), right(Right), count(Count) {} }
; node* root; explicit BST(); node* & search(const Comparable& x) ; const Comparable & findMax(); void insert(Comparable x); void del(const Comparable& x); bool isEmpty() const; size_t size(node* n) const; void printTree(const string & x) const; size_t height() const; const Comparable & rank(size_t x) const; const Comparable & precessor(const Comparable& x); size_t rangeSum(const Comparable& x, const Comparable& y); void rangeSearch(const Comparable& x, const Comparable& y); private: node* & search(node* & root, const Comparable& x) ; node* & findMax(node* & root); void insert(node* & root, Comparable x); void del(node* & root, const Comparable& x); void preOrder( node* const & root) const; //為什麼 root 一定要是常量指標? void postOrder( node* const & root) const; void inOrder( node* const & root) const; void levelOrder( node* const & root) const; size_t height(const node* root) const; const Comparable & rank(size_t x, const node* root) const; Comparable & precessor(const Comparable& x, node* root); node* getNode( //注意要傳入指標的引用才能改變指標 const Comparable& x, node* root, node* & parent, node* & firstRightParent); size_t rangeSum(const Comparable& x, const Comparable& y, node* root); void rangeSearch(const Comparable& x, const Comparable& y, node* root); };
//BST.cpp

#include "BST.h"
#include <queue>


template <typename Comparable>
BST<Comparable>::BST()
{
	root = nullptr;
	
}

template <typename Comparable>
size_t BST<Comparable>::size(node* n) const
{
	return (n == nullptr) ? 0 : n->count;
}

template <typename Comparable>
 typename  BST<Comparable>::node* & BST<Comparable>::search(const Comparable& x)  
{
	return search(root, x);
}

template<typename Comparable>
const Comparable & BST<Comparable>::findMax() 
{
	return findMax(root)->elements;
}

template<typename Comparable>
bool BST<Comparable>::isEmpty() const
{
	return root == nullptr;
}

template<typename Comparable>
void BST<Comparable>::insert(Comparable x)
{
	insert(root, x);
}

template<typename Comparable>
void BST<Comparable>::del(const Comparable& x)
{
	del(root, x);
}

template<typename Comparable>
void BST<Comparable>::printTree(const string & x) const
{
	if (x == "preorder")
		preOrder(root);
	else if (x == "postorder")
		postOrder(root);
	else if (x == "inorder")
		inOrder(root);
	else if (x == "levelorder")
		levelOrder(root);
	else
		throw "Wrong input!";
}

template <typename Comparable>
size_t BST<Comparable>::height() const
{
	return height(root);
}

template <typename Comparable>
const Comparable & BST<Comparable>::rank(size_t x) const
{
	return rank(x, root);
}

template <typename Comparable>
const Comparable & BST<Comparable>::precessor(const Comparable& x) 
{
	return precessor(x, root);
}


template <typename Comparable>
size_t BST<Comparable>::rangeSum(const Comparable& x, const Comparable& y)
{
	return rangeSum(x, y, root);
}

template <typename Comparable>
void BST<Comparable>::rangeSearch(const Comparable& x, const Comparable& y)
{
	rangeSearch(x, y, root);
}

/*private*/
/////////////////////////////
////////////////////////////
///////////////////////////

template <typename Comparable>
void BST<Comparable>::rangeSearch(const Comparable& x, const Comparable& y, node* root)
{
	if (root == nullptr)
		return;
	else if (root->elements >= x && root->elements <= y)
	{
		rangeSearch(x, y, root->left);
		cout << root->elements << endl;
		rangeSearch(x, y, root->right);
	}
	else if (root->elements < x)
		rangeSearch(x, y, root->right);
	else
		rangeSearch(x, y, root->left);
}


template <typename Comparable>
size_t BST<Comparable>::rangeSum(const Comparable& x, const Comparable& y, node* root)
{
	if (root == nullptr)
		return 0;
	else if (root->elements >= x && root->elements <= y)
		return root->elements + rangeSum(x, y, root->left) + rangeSum(x, y, root->right);
	else if (root->elements < x)
		return rangeSum(x, y, root->right);
	else
		return rangeSum(x, y, root->left);
}


template <typename Comparable>
typename  BST<Comparable>::node* BST<Comparable>::getNode(
	const Comparable& x,   node* root,  node* & parent,  node* & firstRightParent)
{
	while (root)
	{
		if (root->elements == x)
			return root;
		
		parent = root;
		
		if (root->elements > x)
			root = root->left;
		else
		{
			firstRightParent = root;
			root = root->right;
		}
	}

	return nullptr;
}

template <typename Comparable>
 Comparable & BST<Comparable>::precessor(const Comparable& x,  node* root) 
{
	if (root == nullptr)
		throw "emptt tree";

	 node* parent = nullptr;
	 node* firstRightParent = nullptr;

	 node* now = getNode(x, root, parent, firstRightParent);

	if (now == nullptr)
		throw "now such value";
	int a = 0;

	if (now->left != nullptr)
		return findMax(now->left)->elements;
	else if (parent == nullptr)
		throw "no precessor";
	else if (parent->right == now)
		return parent->elements;
	else if (firstRightParent == nullptr)
		throw "no precessor";
	else
		return firstRightParent->elements;
}


template <typename Comparable>
const Comparable & BST<Comparable>::rank(size_t x, const node*  root) const
{
	if (root == nullptr)
		throw "empty tree";

	size_t left = size(root->left);
	if (left == x)
		return root->elements;
	else if (left > x)
		return rank(x, root->left);
	else
	
		return rank(x - left - 1, root->right);
	
}


template <typename Comparable>
size_t BST<Comparable>::height(const node* root) const
{
	if (root == nullptr)
		return 0;
	else
	{
		size_t left = height(root->left);
		size_t right = height(root->right);
		return 1 + (left > right ? left : right);
	}
		
}

template<typename Comparable>
typename  BST<Comparable>::node* & BST<Comparable>::search(node* & root, const Comparable& x) 
{
	if (root == nullptr)
		throw "No such element!";
	else if (root->elements == x)
		return root;
	else if (root->elements > x)
		return search(root->left, x);
	else if (root->elements < x)
		return search(root->right, x);

}

template<typename Comparable>
typename BST<Comparable>::node* & BST<Comparable>::findMax(node* & root) 
{
	if (root == nullptr)
		throw "Empty tree!";
	else if (root->right == nullptr)
		return root;
	else
		return findMax(root->right);
}

template<typename Comparable>
void BST<Comparable>::insert(node* & root, Comparable x)
{
	if (root == nullptr)
	{
		root = new node(x, nullptr, nullptr, 1);
		return;
	}
	else if (root->elements < x)
		insert(root->right, x);
	else if (root->elements > x)
		insert(root->left, x);
	else
		; //duplicated value, do nothing

	root->count = size(root->left) + size(root->right) + 1;
}

template<typename Comparable>
void BST<Comparable>::del(node* & root, const Comparable& x)
{
	if (root == nullptr)
		throw "No such elements!";
	else if (root->elements < x)
		del(root->right, x);
	else if (root->elements > x)
		del(root->left, x);
	else
	{
		
		if (root->left == nullptr && root->right == nullptr)//no child
		{
			delete root;
			root = nullptr;
		}
		else if (root->left == nullptr || root->right == nullptr)// one child
		{
			auto temp = root;
			if (root->left == nullptr)
			{
				root = root->right;
				delete temp;
			}
			else if (root->right == nullptr)
			{
				root = root->left;
				delete temp;
			}
		}
		else //two children
		{
			auto & repalce = findMax(root->left);
			root->elements = repalce->elements;
			auto temp = repalce;
			repalce = repalce->left;
			delete temp;
		}
	}
}

template<typename Comparable>
void  BST<Comparable>::preOrder( node* const &  root) const
{
	if (root != nullptr) 
	{
		cout << root->elements << endl;
		preOrder(root->left);
		preOrder(root->right);
	}
}

template<typename Comparable>
void  BST<Comparable>::postOrder(node* const &  root) const
{
	if (root != nullptr)
	{
		postOrder(root->left)
            
           

相關推薦

資料結構演算法總結——查詢及其相關操作

我實現瞭如下操作 插入,查詢,刪除,最大值 樹的高度,子樹大小 二叉樹的範圍和,範圍搜尋 樹的前序,中序,後序三種遍歷 rank 前驅值 在這一版本的程式碼中,我使用了類模板將介面與實現分

資料結構演算法搜尋插入、查詢刪除

1 二叉搜尋樹(BSTree)的概念   二叉搜尋樹又被稱為二叉排序樹,那麼它本身也是一棵二叉樹,那麼滿足以下性質的二叉樹就是二叉搜尋樹,如圖: 若左子樹不為空,則左子樹上所有節點的值都小於根節點的值; 若它的右子樹不為空,則它的右子樹上所有節點的值都大於

資料機構演算法查詢(Binary Search Tree)Java實現

個人總結,如有錯誤,感謝指正 二叉查詢樹(Binary Search Tree) 一、簡介 二叉樹(Binary Tree):每個節點最多有兩個子節點的樹。 二叉查詢樹(binary srarch tree):具有如下性質的二叉樹稱為二叉查詢樹

資料結構演算法14-排序

二叉排序樹 又稱為二叉查詢樹。它或者是一棵空樹,或者是具有下列性質的二叉樹, 1.    若它的左子樹不空,則左子樹上的所有結點的值均小於它的根結構值 2.    若它的右子樹不空,則右子樹上的所有結點的值均

資料結構演算法排序

二叉排序樹 二叉排序樹(Binary Sort Tree),又稱二叉查詢樹(Binary Search Tree),亦稱二叉搜尋樹。是資料結構中的一類。在一般情況下,查詢效率比連結串列結構要高。 二叉排序樹的定義: 當左子樹不為空時,左子樹上的所有節點值都小於左子樹的根節點值 當右子樹不為空時,右子樹

python 資料結構演算法 day05 的深度優先遍歷(縱向)

1. 二叉樹深度優先遍歷三種方式   不同於樹的廣度優先遍歷(一層一層的走,同一層從左到右走完開始走下一層的橫向遍歷方式),深度優先遍歷是一條路走到黑,然後再走下一條;    先序遍歷:根節點--左子節點---右子節點(先從根節點開始,走左子樹,對這個左子樹依然按照根節點

17_資料結構演算法_堆_Python實現

#Created By: Chen Da #先實現一個二叉堆,基於完整二叉樹 class Binary_heap(object): def __init__(self): self.heap_list = [0] #一個空的二叉堆以零作為第一個元素,方

14_資料結構演算法__Python實現

#Created By: Chen Da class BinaryTree(object): def __init__(self,rootObj): self.key = rootObj self.left_child = None sel

資料結構演算法學習--搜尋

可以看下以前對數的總結https://blog.csdn.net/sjin_1314/article/details/8507490 下面是二叉樹的遍歷,建立及銷燬的函式實現,層次遍歷依賴佇列;佇列實現可以去github上檢視https://github.com/jin13417/al

資料結構演算法(Binary Tree)(

今天要講的是二叉查詢樹(Binary Search Tree),是一種最常用的二叉搜尋樹,支援快速查詢,刪除,插入資料。 它是如何實現的呢?,其實它依靠的它的資料結構,在樹中的任意一個節點,其左子樹的每個節點的值都小於這個節點的值,右子樹都大於這個節點的值。 接下來我們來看一下二叉樹是

資料結構演算法(Binary Tree)(一)

好多天沒有寫過資料結構和演算法了,好了今天抽出點時間二叉樹,前面講到的都是線性表,棧,佇列等等。 今天講到的是非線性表結構--樹,首先說一下什麼是樹的概念 樹的這種資料結果挺像我們現實中的樹,這裡的每一個元素我們叫做節點,用線把相鄰的節點連線起來,然後它們就成了父子關係。 A節點是

修煉內功---資料結構演算法29---的儲存

樹和二叉樹的定義和特性,樹這種結構不能簡單通過線性表的前後關係來儲存,線上性表中,一個節點只有至多一個前驅節點和至多一個後驅節點,樹則不然,一個節點可能有多個後驅節點,這個時候,我們需要通過更加複雜的結構才能儲存樹。二叉樹是一種特殊的樹,比多叉樹要簡單,因為特定節點至多隻有兩個節點,這就極大簡化了相

資料結構演算法

二叉樹是一種非常常見並且實用的資料結構,它結合了有序陣列與連結串列的優點。在二叉樹中查詢資料與在陣列中查詢資料一樣快,在二叉樹中新增、刪除資料的速度也和在連結串列中一樣高效,所以有關二叉樹的相關技術一直是程式設計師面試筆試中必考的知識點。 基礎知識 二叉樹(Bi

Javascript之資料結構演算法搜尋實現

Javascript之資料結構與演算法的二叉樹和二叉搜尋樹實現 簡介 程式碼實現 簡介 二叉樹中的節點最多隻能有兩個子節點:一個是左側子節點,另一個是右側子節點。 二叉搜尋樹( BST)是二叉樹的一種,但是它只允許你在

常用資料結構演算法堆(binary heap)

一:什麼是二叉堆 二:二叉堆的實現  三:使用二叉堆的幾個例子 一:什麼是二叉堆 1.1:二叉堆簡介       二叉堆故名思議是一種特殊的堆,二叉堆具有堆的性質(父節點的鍵值總是大於或等於(小於或等於)任何一個子節點的鍵值),二叉堆又具有二叉樹的性質(二叉堆是完全二叉樹

資料結構演算法遞迴非遞迴遍歷(附完整原始碼)

二叉樹是一種非常重要的資料結構,很多其他資料機構都是基於二叉樹的基礎演變過來的。二叉樹有前、中、後三種遍歷方式,因為樹的本身就是用遞迴定義的,因此採用遞迴的方法實現三種遍歷,不僅程式碼簡潔且容易理解,但其開銷也比較大,而若採用非遞迴方法實現三種遍歷,則要用棧來模擬實現(遞迴也

資料結構】進擊的查詢

Description 給定1~N的兩個排列,使用這兩個排列分別構建兩棵二叉查詢樹(也就是通過往一棵空樹中依次插入序列元素的構建方式)。如果這兩棵二叉查詢樹完全相同,那麼輸出YES;否則輸出NO。之後,輸出第一個排列對應的二叉查詢樹的後序序列、層序序列。 Input

資料結構之自平衡查詢(1)

今天開始,我們再來認識一個新的二叉樹,稱為自平衡二叉查詢樹。AVL樹是最先發明的自平衡二叉查詢樹。 AVL樹的特點是:對於樹中的任何節點,節點的左右子樹的高度差距最大為1,所以AVL樹也稱為高度平衡樹。AVL樹得名於它的發明者G.M. Adelson-Velsky和E.M.

資料結構作業:排序及其相關操作

寫了一個簡單的。 因為自己對泛型瞭解的還是不夠到位,所以只能寫個demo版的。 這課樹沒辦法維持平衡,希望以後學一下紅黑樹,替罪羊樹etc.   /* * 簡單的二叉查詢樹 * 沒有自帶旋轉平衡 * 寫完這個我學一下 * avl樹還有紅黑樹 */ public c

資料結構演算法13-哈夫曼及其應用

赫夫曼樹及其應用 最基本的壓縮編碼方法----赫夫曼編碼 定義與原理 我們先把這兩棵二叉樹簡化成葉子結點帶權的二叉樹(注:樹結點間的邊相差的數叫做權Weight) 從樹中一個結點到另一個結點之間的分支構成兩個結點之間的路徑,路徑上的分支數目稱做路徑長度。 如:二叉樹a中,根結點到