Binary Trees

Binary Trees

Introduction

在这里插入图片描述

Full Binary Tree

Each node being either

  • Leaf
  • Internal node with exactly two non-empty children (有孩子必须有两个孩子)

Complete Binary Tree

  • If the height of the tree is d, then all levels except possibly level d-1 are
    completely full
  • The bottom level has all nodes filled in from the left side
    (除了最后一层都是满的,最后一层是从左到右排)

Full Binary Tree Theorem

  • The number of leaves in a non-empty full binary tree is one more than the number of internal nodes. 叶子数=内部节点+1
  • The number of null pointers in a non-empty binary tree is one more than the number of nodes in the tree.空指针数=总节点+1

Node ADT

Template <class Elem> class BinNode { 
public:
virtual Elem& val( ) =0;
virtual BinNode* left( ) const = 0;
virtual BinNode* right( ) const = 0; 
virtual void setVal( const Elem& ) = 0;
virtual void setLeft( BinNode* ) = 0;
virtual void setRight( BinNode* ) = 0;
virtual bool isLeaf( ) = 0;
}
// Binary tree node class
template <class Elem>
class BinNodePtr : public BinNode<Elem> {
private:
Elem it; // The node's value
BinNodePtr* lc; // Pointer to left child
BinNodePtr* rc; // Pointer to right child
public:
BinNodePtr() { lc = rc = NULL; }
BinNodePtr(Elem e, BinNodePtr* l=NULL, BinNodePtr* r=NULL)
{ it = e; lc = l; rc = r; }
Elem& val() { return it; }
void setVal(const Elem& e) { it = e; }
inline BinNode<Elem>* left() const
{ return lc; }
void setLeft(BinNode<Elem>* b)
{ lc = (BinNodePtr*)b; }
inline BinNode<Elem>* right() const
{ return rc; }
void setRight(BinNode<Elem>* b)
{ rc = (BinNodePtr*)b; }
bool isLeaf()
{ return (lc == NULL) && (rc == NULL); }
};

Traversal

在这里插入图片描述

Preorder Traversal

  • Visit each node before visiting its children.
  • ABCDEFGHIJ
template <class Elem>
void preorder(BinNode<Elem>* subroot) {
if (subroot == NULL) return; // Empty
visit(subroot); // Perform some actions
preorder(subroot->left()); // left
preorder(subroot->right()); // right
}

Postorder traversal

  • Visit each node after visiting its children.
  • CBFGEJIHA
template <class Elem>
void postorder(BinNode<Elem>* subroot) {
if (subroot == NULL) return; // Empty
postorder(subroot->left()); // left
postorder(subroot->right()); // right
visit(subroot); // Perform some actions
}

Inorder traversal

  • Visit the left subtree, then the node, then the right subtree.
  • CBAFEGDIH
template <class Elem>
void inorder(BinNode<Elem>* subroot) {
if (subroot == NULL) return; // Empty
inorder(subroot->left()); // left
visit(subroot); // Perform some actions
inorder(subroot->right()); // right
}

Examples

Write a recursive function that returns the height of a binary tree

template <class Elem>
int findHeight(BinNode<Elem>* subroot){
if (subroot == NULL) return 0; // Empty subtree
return 1 + max(height(subroot->left()), 
height(subroot->right()));
}

Write a recursive function that search value K in a binary tree. The function returns true if value K is exist

template <class Key, class Elem, class KEComp>
bool search(BinNode<Elem>* subroot, Key K){...}
if (subroot == NULL) return false;
if (subroot->value() == K) return true;
elseif (search(subroot->left())) return true;
else return search(subroot->right());
}

Binary Search Trees

Introduction

  • All elements stored in the left subtree of a node with value K have values < K
  • All elements stored in the right subtree of a node with value K have values >= K

ADT

// BST implementation for the Dictionary ADT
template <class Key, class Elem, class KEComp, class EEComp>
class BST : public Dictionary<Key, Elem,KEComp, EEComp> {
private:
	BinNode<Elem>* root; // Root of the BST
	int nodecount; // Number of nodes
	void clearhelp(BinNode<Elem>*);
	BinNode<Elem>* inserthelp(BinNode<Elem>*, const Elem&);
	BinNode<Elem>* deletemin(BinNode<Elem>*,BinNode<Elem>*&);
	BinNode<Elem>* removehelp(BinNode<Elem>*,const Key&,BinNode<Elem>*&);
	bool findhelp(BinNode<Elem>*, const Key&,Elem&) const;
	void printhelp(BinNode<Elem>*, int) const;
public:
	BST() { root = NULL; nodecount = 0; }
	~BST() { clearhelp(root); } 
	void clear() { clearhelp(root); root = NULL; nodecount = 0;}
}

INSERTHELP

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>::inserthelp( BinNode<Elem>* subroot, const Elem& val ) {
	if (subroot == NULL) // Empty: create node 
		return new BinNodePtr<Elem>(val,NULL,NULL);
	if (EEComp::lt(val, subroot->val()))
		subroot->setLeft(inserthelp(subroot->left(), val));
	else 
		subroot->setRight(inserthelp(subroot->right(), val));
	return subroot; // Return subtree with node inserted
}

根据搜索树特性寻找,在空指针处插值。
注意这里是把值一层一层返回给上级。
在这里插入图片描述
DELETEMIN

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::deletemin(BinNode<Elem>* subroot, BinNode<Elem>*& min) {
	if (subroot->left() == NULL) {
		min = subroot;
		return subroot->right();
	}
	else { // Continue left
		subroot->setLeft(
		deletemin(subroot->left(), min));
		return subroot;
	}
}

找到最小值就让min指向它,并没有真正的删除。
用最小值节点的右子树(排序下来之比最小值节点大一个)的节点代替最小值节点的位置。
REMOVEHELP

template <class Key, class Elem, class KEComp, class EEComp>
	BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>::removehelp(BinNode<Elem>* subroot, const Key& K, BinNode<Elem>*& t) {
	//查找部分
	if (subroot == NULL) return NULL;
	else if (KEComp::lt(K, subroot->val())) 
		subroot->setLeft(removehelp(subroot->left(), K, t));
	else if (KEComp::gt(K, subroot->val()))
		subroot->setRight(removehelp(subroot->right(), K, t));
	//以下是找到了k值点
	else { // Found it: remove it
		BinNode<Elem>* temp;
		t = subroot;
		//无左子树,直接把右子树接上
		if (subroot->left() == NULL)
			subroot = subroot->right();
		//无右子树,直接把左子树接上
		else if (subroot->right() == NULL)
			subroot = subroot->left();
		//两个子树都有,选择右子树的最小节点来和父节点交换。
		else { // Both children are non-empty
			subroot->setRight(deletemin(subroot->right(), temp));
			//此处temp接受了右子树最小值的返回值
			//交换操作
			Elem te = subroot->val();
			subroot->setVal(temp->val());
			temp->setVal(te);
			//t用来返回被删除节点的值
			t = temp;
		} 
	}
	return subroot;
}
  1. 先进行常规的搜索操作
  2. 找到待删除节点
    • 无左子树,直接用右子树替换
    • 无右子树,直接用左子树替换
    • 都有,选择右子树的最小节点来和该节点交换
      (如果选左子树最大节点可能会在替换时发生问题(注意右子树是大于+等于))

CLEARHELP

template <class Key, class Elem, class KEComp, class EEComp>
	void BST<Key,Elem,KEComp,EEComp>::clearhelp(BinNode<Elem>* subroot) {
		if (subroot == NULL) return;
		clearhelp(subroot->left());
		clearhelp(subroot->right());
		delete subroot;
	}

其实就是postorder遍历+删除。
PRINTHELP

template <class Key, class Elem, class KEComp, class EEComp>
	void BST<Key,Elem,KEComp,EEComp>::printhelp(BinNode<Elem>* subroot, int level) {
		if (subroot == NULL) return NULL;
		printhelp(subroot->left(), level+1);
		for (int i=0; i<level; i++)	cout << “ “;
		cout << subroot->val() << “\n”;
		printhelp(subroot->right(), level+1);
	}

INSERT

bool insert(const Elem& e) {
	root = inserthelp(root, e);
	nodecount++;
	return true; 
}

REMOVE

bool remove(const Key& K, Elem& e) {
	BinNode<Elem>* t = NULL;
	root = removehelp(root, K, t);
	if (t == NULL) return false;
	e = t->val();
	nodecount--;
	delete t;
	return true; 
}

Priority Queues and Heaps

Array-Based Complete BT

  • P a r e n t ( r ) = ⌊ ( r − 1 ) / 2 ⌋    i f    r ≠ 0    a n d    r < n Parent (r) = \lfloor (r - 1) / 2\rfloor\ \ if \ \ r ≠ 0\ \ and\ \ r < n Parent(r)=(r1)/2  if  r=0  and  r<n
  • L e f t c h i l d ( r ) = 2 r + 1    i f    2 r + 1 < n Leftchild(r) = 2r + 1\ \ if \ \ 2r+1 < n Leftchild(r)=2r+1  if  2r+1<n
  • R i g h t c h i l d ( r ) = 2 r + 2    i f    2 r + 2 < n Rightchild(r) = 2r + 2\ \ if\ \ 2r +2 < n Rightchild(r)=2r+2  if  2r+2<n
  • L e f t s i b l i n g ( r ) = r − 1    i f    r    i s    e v e n ,   r > 0    a n d    r < n Leftsibling(r) = r - 1\ \ if\ \ r\ \ is\ \ even,\ r > 0 \ \ and\ \ r < n Leftsibling(r)=r1  if  r  is  even, r>0  and  r<n
  • R i g h t s i b l i n g ( r ) = r + 1    i f    r    i s    o d d ,   r + 1 < n Rightsibling(r) = r + 1\ \ if \ \ r\ \ is\ \ odd, \ r +1 < n Rightsibling(r)=r+1  if  r  is  odd, r+1<n
    在这里插入图片描述

Heaps

Properties
  • Complete Binary Tree
  • Value stored in a heap are partially ordered
Types
  • Min-heap: All values less than or equal to child values
    在这里插入图片描述

    • Max-heap: All values greater than or equal to childvalues
      在这里插入图片描述
ADT
template<class Elem,class Comp> class maxheap{
private:
	Elem* Heap; // Pointer to the heap array
	int size; // Maximum size of the heap
	int n; // Number of elems now in heap
	void siftdown(int); // Put element in place
public:
	maxheap(Elem* h, int num, int max);
	int heapsize() const;
	bool isLeaf(int pos) const;
	int leftchild(int pos) const;
	int rightchild(int pos) const;
	int parent(int pos) const;
	bool insert(const Elem&);
	bool removemax(Elem&);
	bool remove(int, Elem&);
	void buildHeap();
};

Buildheap Function

public void buildheap() // Heapify contents
{ 
	for (int i=n/2-1; i>=0; i--) //逐个更新,对于leaf不用叫shiftdown
		siftdown(i); //注意这里是从下往上换的
}
	
template <class Elem, class Comp>
void maxheap<Elem,Comp>::siftdown(int pos) {
	while (!isLeaf(pos)) { //没必要更新leaf(这里都只是父节点和子节点比较,leaf无子节点)
		int j = leftchild(pos); //用j,rc 获取左右节点的值
		int rc = rightchild(pos);
		if ((rc<n) && Comp::lt(Heap[j],Heap[rc])) //保证rc不为空(n是个数)
			j = rc; //j永远指向两个子结点中大的那个
		if (!Comp::lt(Heap[pos], Heap[j])) //如果当前节点比最大子节点大 结束
			return;//用于没有交换操作,不用管下面的节点
		swap(Heap, pos, j); //如果小于,交换两个的值(不交换指针位置)
		pos = j;//沿着被交换的节点继续向下递归
	}
}

** Removemax Function**

template <class Elem, class Comp>
bool maxheap<Elem, Comp>:: removemax(Elem& it) {
	if (n == 0) return false; // Heap is empty
	swap(Heap, 0, --n); // Swap max with end
	if (n != 0) siftdown(0);//防止仅有一个节点
	it = Heap[n]; // Return max value
	return true;
}

Remove Function

template <class Elem, class Comp>
bool maxheap<Elem, Comp>::remove(int pos, Elem& it) {
	bool flag = false;//用来表示替换节点的大小,大于父节点是true,小于是false
	if ((pos < 0) || (pos >= n)) return false;//防止pos位置为空
	//交换删除节点和最后一个节点的值
	swap(Heap, pos, --n);//先减再交换(从0标号)
	//如果当前位置比父节点大
	while ((pos != 0) && (Comp::gt(Heap[pos],Heap[parent(pos)]))){
		swap(Heap, pos, parent(pos));//交换当前节点和父节点的值
		pos = parent(pos);//pos始终指着比较大的一个
		flag=true;
	}
	//如果大于父节点,一定大于父节点的子节点
	//此处是对于没有大于父节点的向下替换操作
	if (!flag) siftdown(pos);
	it = Heap[n];//用于返回被删除的值
	return true;
}

Insert Function

template <class Elem, class Comp> // Insert element
bool maxheap<Elem, Comp>::insert(const Elem& val) {
	if (n >= size) return false; // Heap is full
	int curr = n++;
	Heap[curr] = val; // Start at end of heap
	// Now sift up until curr's parent > curr
	while ((curr!=0) && (Comp::gt(Heap[curr], Heap[parent(curr)]))){
		swap(Heap, curr, parent(curr));
		curr = parent(curr);
	}
	return true;
}
Creat a Heap
  • Buildheap Function : Θ ( l o g   n ) \Theta(log\ n) Θ(log n)
  • Insert n values to a heap using insert function : Θ ( n ) \Theta(n) Θ(n)

Priority Queues

  • Linked List
    • Insert appends to a linked list ( O ( 1 ) O(1) O(1) )
    • Remove max value determines the maximum by scanning the list ( O ( n ) O(n) O(n) )
  • Sorted Linked List (decreasing order)
    • Insert places an element in its correct position ( O ( n ) O(n) O(n) )
    • Remove max value simply removes the head of the list ( O ( 1 ) O(1) O(1) )
  • Heap
    • Both insert and remove max value are O ( l o g n ) O( log n ) O(logn) operations

Huffman Coding Trees

  • Combine the two smallest values each time
    在这里插入图片描述
  • Prefix Property : No code in the set is the prefix of another
  • E x p e c t e d   C o s t   p e r   l e t t e r = ∑ f r e q u e n c y × b i t ∑ f r e q u e n c y Expected\ Cost\ per\ letter=\frac{\sum frequency × bit }{\sum frequency} Expected Cost per letter=frequencyfrequency×bit
ADT
template <class Elem>
class HuffNode { // Node abstract base class
public:
	virtual int weight() = 0;
	virtual bool isLeaf() = 0;
	virtual HuffNode* left() const = 0;
	virtual void setLeft(HuffNode*) = 0;
	virtual HuffNode* right() const = 0;
	virtual void setRight(HuffNode*) = 0;
};

FreqPair

template <class Elem>
class FreqPair { // An element/frequency pair
	private:
		Elem it; // An element of some sort
		int freq; // Frequency for the element
	public:
		FreqPair(const Elem& e, int f) // Constructor
			{ it = e; freq = f; }
		~FreqPair() { } // Destructor
		int weight() { return freq; } // Return the weight
		Elem& val() { return it; } // Return the element
};
**Leaf Node**
```cpp
template <class Elem> // leaf node subclass
class LeafNode: public HuffNode<Elem> {
private:
	Freqpair<Elem>* it; // Frequency pair
public:
	LeafNode(const Elem& val, int freq) //constructor
		{ it = new Freqpair<Elem>(val,freq); }
	int weight() { return it->weight(); } //Return frequency
	Freqpair<Elem>* val() { return it; }
	bool isLeaf() { return true; }
	virtual HuffNode* left() const { return NULL; }
	virtual void setLeft(HuffNode*) { }
	virtual HuffNode* right() const { return NULL; }
	virtual void setRight(HuffNode*) { }
};

Internal Node

template <class Elem> //Internal node subclass
class IntlNode: public HuffNode<Elem> {
private:
	HuffNode<Elem>* lc; //left child
	HuffNode<Elem>* rc; //right child
	int wgt; //Subtree weight
public:
	IntlNode(HuffNode<Elem> * l; HuffNode<Elem> * r)
		{ wgt = l->weight() + r->weight(); lc = l; rc = r; }
	int weight() { return wgt; } // Return frequency
	bool isLeaf() { return false; }
	HuffNode<Elem>* left() const { return lc; }
	void setLeft(HuffNode<Elem>* b) { lc = (HuffNode*)b; }
	HuffNode<Elem>* right() const { return rc; }
	void setRight(HuffNode<Elem>* b) { rc = (HuffNode*)b; }
};

Huffman Tree

template <class Elem>
class HuffTree {
private:
	HuffNode<Elem>* theRoot;
public:
	HuffTree(Elem& val, int freq) 
		{ theRoot = new LeafNode<Elem>(val,freq);}
	HuffTree(HuffTree<Elem>* l, HuffTree<Elem>* r)
		{ theRoot = new IntlNode<Elem>(l->root(), r->root());}
	~HuffTree() {}
	HuffNode<Elem>* root() { return theRoot; }
	int weight() { return theRoot->weight(); }
};

Huffman Compare

template <class Elem> class HHCompare {
public:
	static bool lt(HuffTree<Elem>* x, HuffTree<Elem>* y)
		{ return x->weight() < y->weight(); }
	static bool eq(HuffTree<Elem>* x, HuffTree<Elem>* y)
		{ return x->weight() = = y->weight(); }
	static bool gt(HuffTree<Elem>* x, HuffTree<Elem>* y)
		{ return x->weight() > y->weight(); }
};

Build Huffman Tree

template <class Elem> HuffTree<Elem>*
//SLL->Sorted Linked List
buildHuff(SLList<HuffTree<Elem>*,HHCompare<Elem>>* f1){
//估计setStart()是把f1放到合适的位置
	HuffTree<Elem>* temp1, *temp2, *temp3;
	for (f1->setStart();
	f1->leftLength() + f1->rightLength()>1;
	f1->setStart()) { //While at least two items left
		f1->remove(temp1); // Pull first two trees off the list
		f1->remove(temp2);
		temp3 = new HuffTree<Elem>(temp1, temp2);
		f1->insert(temp3); // Put the new tree back on list
		delete temp1; // Delete the remnants
		delete temp2;
	}
	return temp3;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值