二叉树结构--基础

来源:互联网 发布:用友好会计软件 编辑:程序博客网 时间:2024/04/29 20:20

template <typename Key,typename E>class BSTNode :public BinNode<E> {private:Key key;E item;BSTNode* lc;BSTNode* rc;public:BSTNode() { lc = rc = NULL; }BSTNode(Key k, E it, BSTNode* lc=NULL, BSTNode* rc=NULL) {key = k; item = it; this.lc = 

一. 基本概念:树是简单连通图,二叉树是2元树,一个结点最多只能有两个子结点

结点:包含一个数据元素及若干指向子树的分支

子结点:结点的子树的根称为该结点的孩子

父结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲

祖先:从根到该结点的所经分支上的所有结点

后代:以某结点为根的子树中任一结点都称为该结点的子孙

结点的度:结点子树的个数

叶子结点:也叫终端结点,是度为 0 的结点;

内部结点:度不为0的结点

结点层:根结点的层定义为0(外国教材),中文教材定义为1

深度:树中最大的结点层

高度:从1开始


二.特殊二叉树分类:

(1)满二叉树(full binary tree) :除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树

两个定理:a. 叶子结点的数目总比内部结点多1(数学归纳法)

                  b. 空子树的数目比叶子结点的数目多1

(2)完全二叉树(complete bianary tree): 若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布


三. Binaru Tree Node ADT

class BinNode {public:virtual ~BinNode() {}virtual E& element() = 0;virtual void setElement(const E&) = 0;virtual BinNode* left() const = 0;virtual void setLeft(BinNode*) = 0;virtual BinNode* right()const = 0;virtual void setRight(BinNode*) = 0;virtual bool isLeaf() = 0;};


( 1 ) 顺序存储结构

有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:

若I为结点编号则 如果I>1,则其父结点的编号为I/2;

如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;

如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。

(2)链式存储结构

template <typename Key,typename E>class BSTNode :public BinNode<E> {private:Key key;E item;BSTNode* lc;BSTNode* rc;public:BSTNode() { lc = rc = NULL; }BSTNode(Key k, E it, BSTNode* lc=NULL, BSTNode* rc=NULL) {key = k; item = it; this.lc = lc;  this.rc = rc;}~BSTNode() {}E& element() {return item;}void setElement(const E& it) { item = it; }Key& getkey() {return key;}void setKey(Key& k) { key = k;}BSTNode* left()const { return lc; }void setLeft(BinNode* l) { lc = (BSTNode*)l; }BSTNode* right()const { return rc; }void setRight(BinNode* r) { rc = (BSTNode*)r; }bool isLeaf() {return (lc == NULL) && (rc == NULL);}};


四. 二叉树遍历(traversal )
设L、D、R分别表示遍历左子树、访问根结点和遍历右子树, 则对一棵二叉树的遍历有三种情况:DLR(称为先根次序遍历),LDR(称为中根次序遍历),LRD (称为后根次序遍历)。
遍历中不断的用到递归。
先序遍历如下:
template<typename E>void preorder(BinNode<E>* root) {if (root == 0) return;cout << root->element() << " ";if(root->left()!=NULL)  preorder(root->left());if(root->right()!=NULL) preorder(root->right());}



五. 用二叉树来实现二叉搜索树(Binary Search Tree )

//Binary Search Treetemplate <typename K,typename E>class BST {private:BSTNode<K, E>* root;int nodecount;//插入并返回插入点的根结点,递归BSTNode<K, E>* inserthelp(BSTNode<K, E>* root, const K& key, const E& elem) {if (root == NULL) return new BSTNode<K, E>(key, elem);else if (root->getkey() > key)  root->setLeft(inserthelp(root->left(), key, elem));else root->setRight(inserthelp(root->right(), key, elem));return root;}//递归E findhelp(BSTNode<K, E>* root, const K& key) {if (root == NULL) return;else if (root->getkey() > key) return findhelp(root->left(), key);else if (root->getkey() < key) return findhelp(root->right(), key);else return root->element;}//删除最小值,不断往左边递归就好,返回删除的最小值后的该处应该放置的结点BSTNode<K, E>* deletemin(BSTNode<K, E>*rt) {if (rt->left() == NULL) {BSTNode<K, E>* rightnode = rt->right();delete rt;return rightnode;}else {rt->setLeft(deletemin(rt->left()));return rt;}}BSTNode<K, E> getmin(BSTNode<K, E>* rt) {if (rt->left() == NULL)return rt;else return getmin(rt->left());}//根据key值删除结点BSTNode<K, E> removehelp(BSTNode<K, E>* root, const K& key) {if (root == NULL) return NULL;else if (key < root->getkey()) removehelp(root->left(), key);else if (key > root->getkey()) removehelp(root->right(), key);else {BSTNode<K, E>* temp = root;if (root->left() == NULL) {//左结点为空root=root->right();delete temp;}else if (root->right() == NULL) {//右结点为空root = root->left();delete temp;}else {//左右结点均不为空temp = getmin(root->right());root->setElement(temp->element);root->setKey(temp->key());root->setRight(deletemin(root->right()));delete temp;}}return root;}public:BST() {root = NULL;nodecount = 0;}void insert(const K& key, const E& elem) {root = inserthelp(root, key, elem);nodecount++;}E find(const K& key) {return findhelp(root, key);}int size() { return nodecount; }E removeAny() {if (root == NULL) return NULL;else {E temp = root->element;root = removehelp(root, root->getkey());nodecount--;return temp;}}};



六. 用二叉树来实现二叉堆(Binary Heap )

完全二叉堆具有堆的性质,所以一般用二叉树的顺序存储结构来实现二叉堆

//最大值堆class Heap {private:int* heap;int maxSize;int n;void shiftdown(int pos) {//不断向下调整位置while (!isLeaf(pos)) {int lc = leftchild(pos);if ((lc + 1 < n) && (heap[lc] < heap[lc + 1]))  lc + 1;if (heap[pos] > heap[lc]) break;swap(heap[pos], heap[lc]);pos = lc;}}public:Heap(int n=100) {maxSize = n;heap = new int[maxSize];n = 0;}Heap(int* h, int num, int ms) {heap = h;n = num;maxSize = ms;buildHeap();}int size() { return n; }bool isLeaf(int pos) {if ((pos >= n / 2) && (pos < n))return true;elsereturn false;}int leftchild(int pos) {assert(pos < n / 2);return pos * 2+1;}int rightchild(int pos) {assert(pos < n / 2);return pos * 2 + 2;}int parent(int pos) {assert(pos > 0);return (pos - 1) / 2;}void buildHeap() {//从最后一个内部结点开始往回,每一个都要shiftdown操作for (int i = (n / 2 - 1); i >= 0; i--) {shiftdown(i);}}void insert(const int& it) {assert(n <= maxSize);heap[n] = it;int curr=n++;while (curr > 0 && (heap[curr] > heap[parent(curr)])){swap(heap[curr], heap[parent(curr)]);curr = parent(curr);}}int removefirst() {assert(n > 0);int max = heap[0];swap(heap[0], heap[--n]);if (n != 0) shiftdown(0);return max;}int remove(int pos) {assert((pos < n) && (pos >= 0));if (pos == (n - 1)) { return heap[--n]; }else {swap(heap[pos], heap[--n]);while ((pos != 0) && (heap[pos] > heap[parent(pos)])) {swap(heap[pos], heap[parent(pos)]);pos = parent(pos);}}if (pos != 0) shiftdown(pos);return heap[n];}};