二叉树及二叉搜索树

 

第十章  二叉树

学习目的

学习广义树的定义,熟悉树的有关术语

理解树是一种非线性的数据结构

理解很多有关树的操作都涉及到二叉树,所谓二叉树是指每个父结点最多包含两个子结点

掌握一棵n个结点的完全二叉树的高度是 int(log2n),这样的对是沿着从根开始的路径来寻找数据的

理解树的退化,面成为像链表一样的高效的存储结构

学习二叉树的实现,使用tnode对象来保存数据以及指向左、右子树的指针

理解6种树扫描的递归算法,最常用的3种算法是:中序,后序和前序遍历

学习使用队列逐层扫描树的算法

通过学习一系列实际应用,熟悉二叉树的相关算法

理解二叉搜索树的结构。理解二叉树按照结点的值,而不是结点的位置来保存数据。熟悉它的ADT

注意二叉搜索树是关联容器的特例

学习树的iterator类的实现

10.1树结构

根结构:在一棵树中,有一个唯一的起始点,称为根结点。每一个结点包含一个值和零个或多个指向

        后继的结点的指针。

边:从父结点指向子结点的连接称为边。

叶子结点:没有子结点的称为叶子结点。

层次:任何结点到它或其子结点只有唯一的一条路径。从根结点到任何结点的路径长度为每一个结点

定义了一种度量,称为层次。根结点的层次是0

树的高度:定义为树中所有结点层次的最大值.高度的概念也可以用路径来解释.树的高度是所有从根

结点到其他结点的路径中长度的最大值.

建立二叉树

二叉树由动态分配的结点对象构成,这些结点对象的指针指向自己的子结点。

树图

 

见代码chapter10.1

代码chapter10.2的树图

功能:建立如下二叉树,前序遍历,按层次遍历二叉树,拷贝二叉树,删除树

 

树图2

 

10.5 二叉搜索树

将二叉树设计成在能够存储大量数据的同时,又能为程序员提供方便高效的访问和更新元素的操作.最终得到的容器结构为二叉搜索树,......是所有关联容器的原型.

按元素值来存储的关联容器.

二叉树是由各个结点组成的数据结构,从根结点到其他结点之间只有唯一的路径.为了将二叉树设计成有效的存储容器,我们必须实现一种次序,把结点的值与它所处的路径联系起来.这种次序使得我们可以根据值来找到对应元素的位置.由于这个原因,这种存储容器称为二叉搜索树.

排序:对于每个结点,其左子树的所有结点的值都比它小,而其右子树中所有结点的值都比它大.

10.5.3二叉搜索树中的数据查找

   每个结点都有一个唯一的路径.这个路径既可以用来插入,也可以用来查找元素.比较当前结点与待查找的元素,如果相等,则找到元素;否则,如果待查找元素小于当前结点,则查找左子树;如果大于当前结点,则查找右子树.如果最后达到空树,则称没有找到该值.

见代码chapter10.5

chapter10.1

// Tnode.h

 

// 表示ercas二叉树的一个结点

template<class T>   class Tnode

{

public:

 T nodeValue;

 Tnode * left, *right; // 左右子结点指针

 // 默认的构造函数,数据初始化

 Tnode(){}

 // 初始化数据成员

 Tnode(const T & item, Tnode<T> * lptr = NULL, Tnode<T> * rptr = NULL)

  : nodeValue(item), left(lptr),right(rptr)

 {}

 

};

// main.cpp

 

#include <iostream>

#include "Tnode.h"

#include <string>

using namespace std;

template<class T>  void pre_order(Tnode<T> * node);

int main()

 {

     Tnode<int> * root, * p, * q, * r;

  p = new Tnode<int>(20);

     q = new Tnode<int>(40);

  r = new Tnode<int>(30,q );

  root = new Tnode<int>(10,p,r);

  pre_order( root );

  return 0;

 }

template<class T>  void pre_order(Tnode<T> * node)

{

      if( node != NULL )

   {

    cout << node->nodeValue << endl;

    pre_order(node->left);

    pre_order(node->right);

   }

}

 

/chapter10.2

// Tnode.h

 

#ifndef  BINTREE_H

#define  BINTREE_H

// 表示ercas二叉树的一个结点

#include <iostream>

using std::cout;

using std::endl;

template<class T>   class Tnode

{

 

public:

 T nodeValue;

 Tnode * left, *right; // 左右子结点指针

 // 默认的构造函数,数据不有初始化

 Tnode(){}

 // 初始化数据成员

 Tnode(const T & item, Tnode<T> * lptr = NULL, Tnode<T> * rptr = NULL)

  : nodeValue(item), left(lptr),right(rptr)

 {}

 void setLeftNode(Tnode<T> * child_left)

 { left = child_left; }

 void setRightNode( Tnode<T> * child_right )

 { right = child_right; }

 ~Tnode()

 { cout << "delete node that's value is " << nodeValue << endl; }

 

};

 

template<class T>  class BinaryTree

{

public:

 BinaryTree() : root(NULL)

 { count_leaf = 0;idepth=0;}

 void build_tree();

 //前序遍历二叉树

    void pre_order();

 // 按层次遍历二叉树

 void level_order()

 { level_order(root); }

 // 叶子结点计数

 int getCountLeaf();

 // 计算树的深度

 int depth();

 // 得到根结点

 const Tnode<T> * getRoot()

 return root; }

 // 设置根结点

 void setRoot( Tnode<T> * root_pa )

 {  root = root_pa; }

    Tnode<T> * copy_tree(const Tnode<T> * source);

 void delete_tree()

 { delete_tree(root); }

protected:

 Tnode<T> * root;

 int count_leaf;

 int idepth;

    void pre_order(Tnode<T> * node);

 void level_order(Tnode<T> * node);

 void getCountLeaf(Tnode<T> * node);

 int depth(Tnode<T> * node);

 void delete_tree(Tnode<T> * node);

};

 

#endif

 

// BinaryTree.cpp

 

 

#include "Tnode.h"

#include <deque>

using std::max;

 

 

template<class T> void BinaryTree<T>::build_tree()

{

 Tnode<char> * p,*pr,* lt, * rt, * oldp;

 lt = new Tnode<char>('G');

 p = new Tnode<char>('E',lt); // E子树

 lt = new Tnode<char>('D'); // E的兄弟结点

 p = new Tnode<char>('B',lt,p); // B 子树

    lt = new Tnode<char>('H');

 rt = new Tnode<char>('J');

 pr = new Tnode<char>('F',lt,rt); // F子树

    pr = new Tnode<char>('C',NULL,pr);// C子树

 p = new Tnode<char>('A',p, pr);

 root = p;

 

}

template<class T>  void BinaryTree<T>::pre_order()

{

      pre_order( root );

}

template<class T>  void BinaryTree<T>::pre_order(Tnode<T> * node)

{

      if( node != NULL )

   {

    cout << node->nodeValue << endl;

    pre_order(node->left);

    pre_order(node->right);

   }

}

template<class T>  void BinaryTree<T>::level_order(Tnode<T> * node)

{

 using std::deque;

 deque<Tnode<T> * >  dq;

 Tnode<T> * temp;

 dq.push_back( node );

 

 while ( !dq.empty() )

 {

  temp = dq.front();

  dq.pop_front();

  cout << temp->nodeValue;

  if (NULL != temp->left )

   dq.push_back(temp->left);

  if (NULL != temp->right )

   dq.push_back(temp->right);

 

}

template<class T>  int BinaryTree<T>::getCountLeaf()

{

    getCountLeaf( root );

 return count_leaf;

}

template<class T>  void BinaryTree<T>::getCountLeaf(Tnode<T> * node)

{  

      if( node != NULL )

   {

          if ( NULL == node->left && NULL == node->right )

       count_leaf++;

    getCountLeaf(node->left);

    getCountLeaf(node->right);

   }

}

template<class T>  int BinaryTree<T>::depth()

{

 int d = depth(root);

 return d;

}

template<class T>  int BinaryTree<T>::depth(Tnode<T> * node)

{

 if ( NULL == node )

  return -1;

  return 1 + max(depth(node->left),depth(node->right));

}

template<class T> Tnode<T> *  BinaryTree<T>::copy_tree(const Tnode<T> * source)

{

        if ( NULL == source )

    return  NULL;

  

  Tnode<T> * p = new Tnode<T>( source->nodeValue );

  Tnode<T> * pl, * pr;

  pl = copy_tree(source->left );

  p->setLeftNode( pl );

  pr = copy_tree(source->right);

  p->setRightNode( pr );

  return p;

}

 

template<class T> void BinaryTree<T>::delete_tree(Tnode<T> * node)

{

 

 // 采用后序遍历,保证先删除子结点,再删除父结点

 if ( NULL != node )

 {

         delete_tree(node->left);

   delete_tree(node->right);

   delete node;

 }

 

}

 

// main.cpp

#include <iostream>

 

#include "Tnode.h"

#include "BinaryTree.cpp"

#include <string>

using namespace std;

 

int main()

 {

     BinaryTree<char> bintree;

  bintree.build_tree();

  int count = bintree.getCountLeaf();

  cout << "leaf count = " << count << endl;

  int d = bintree.depth();

  cout << "depth of tree = " << d << endl;

  BinaryTree<char> tree_backup;

  Tnode<char> * p = tree_backup.copy_tree( bintree.getRoot() );

  tree_backup.setRoot( p );

  tree_backup.level_order();

  tree_backup.pre_order();

  cout << "the address of bintree root = " << bintree.getRoot() << endl;

  cout << " the address of tree_backup = " << tree_backup.getRoot() << endl;

  bintree.delete_tree();

  return 0;

 }

/

chapter10.5二叉搜索树 插入加查找

 

#ifndef  BINTREE_H

#define  BINTREE_H

// 表示ercas二叉树的一个结点

#include <iostream>

using std::cout;

using std::endl;

template<class T>   class Tnode

{

 

public:

 T nodeValue;

 Tnode * left, *right; // 左右子结点指针

 // 默认的构造函数,数据不有初始化

 Tnode(){}

 // 初始化数据成员

 Tnode(const T & item, Tnode<T> * lptr = NULL, Tnode<T> * rptr = NULL)

  : nodeValue(item), left(lptr),right(rptr)

 {}

 void setLeftNode(Tnode<T> * child_left)

 { left = child_left; }

 void setRightNode( Tnode<T> * child_right )

 { right = child_right; }

 ~Tnode()

 { cout << "delete node that's value is " << nodeValue << endl; }

 

};

 

template<class T>  class BinaryTree

{

public:

 BinaryTree() : root(NULL)

 { count_leaf = 0;idepth=0;}

 void build_tree();

 //前序遍历二叉树

    void pre_order();

 // 按层次遍历二叉树

 void level_order()

 { level_order(root); }

 // 叶子结点计数

 int getCountLeaf();

 // 计算树的深度

 int depth();

 // 得到根结点

 const Tnode<T> * getRoot()

 return root; }

 // 设置根结点

 void setRoot( Tnode<T> * root_pa )

 {  root = root_pa; }

    Tnode<T> * copy_tree(const Tnode<T> * source);

 void delete_tree()

 { delete_tree(root); }

 void insert(const T & t)

 {    insert( t, root, NULL, 1); 

 }

 bool find(const T & t)

 {  return find(t,root); }

protected:

 Tnode<T> * root;

 int count_leaf;

 int idepth;

    void pre_order(Tnode<T> * node);

 void level_order(Tnode<T> * node);

 void getCountLeaf(Tnode<T> * node);

 int depth(Tnode<T> * node);

 void delete_tree(Tnode<T> * node);

 void insert(const T & t, Tnode<T> * current, Tnode<T> * parent, int flag);

 bool find(const T & t, Tnode<T> * current);

 

};

 

#endif

 

// BinaryTree.cpp

 

#include "Tnode.h"

#include <deque>

using std::max;

 

 

template<class T> void BinaryTree<T>::build_tree()

{

 Tnode<char> * p,*pr,* lt, * rt, * oldp;

 lt = new Tnode<char>('G');

 p = new Tnode<char>('E',lt); // E子树

 lt = new Tnode<char>('D'); // E的兄弟结点

 p = new Tnode<char>('B',lt,p); // B 子树

    lt = new Tnode<char>('H');

 rt = new Tnode<char>('J');

 pr = new Tnode<char>('F',lt,rt); // F子树

    pr = new Tnode<char>('C',NULL,pr);// C子树

 p = new Tnode<char>('A',p, pr);

 root = p;

 

}

template<class T>  void BinaryTree<T>::pre_order()

{

      pre_order( root );

}

template<class T>  void BinaryTree<T>::pre_order(Tnode<T> * node)

{

      if( node != NULL )

   {

    cout << node->nodeValue << endl;

    pre_order(node->left);

    pre_order(node->right);

   }

}

template<class T>  void BinaryTree<T>::level_order(Tnode<T> * node)

{

 using std::deque;

 deque<Tnode<T> * >  dq;

 Tnode<T> * temp;

 dq.push_back( node );

 

 while ( !dq.empty() )

 {

  temp = dq.front();

  dq.pop_front();

  cout << temp->nodeValue;

  if (NULL != temp->left )

   dq.push_back(temp->left);

  if (NULL != temp->right )

   dq.push_back(temp->right);

 

}

template<class T>  int BinaryTree<T>::getCountLeaf()

{

    getCountLeaf( root );

 return count_leaf;

}

template<class T>  void BinaryTree<T>::getCountLeaf(Tnode<T> * node)

{  

      if( node != NULL )

   {

          if ( NULL == node->left && NULL == node->right )

       count_leaf++;

    getCountLeaf(node->left);

    getCountLeaf(node->right);

   }

}

template<class T>  int BinaryTree<T>::depth()

{

 int d = depth(root);

 return d;

}

template<class T>  int BinaryTree<T>::depth(Tnode<T> * node)

{

 if ( NULL == node )

  return -1;

  return 1 + max(depth(node->left),depth(node->right));

}

template<class T> Tnode<T> *  BinaryTree<T>::copy_tree(const Tnode<T> * source)

{

        if ( NULL == source )

    return  NULL;

  

  Tnode<T> * p = new Tnode<T>( source->nodeValue );

  Tnode<T> * pl, * pr;

  pl = copy_tree(source->left );

  p->setLeftNode( pl );

  pr = copy_tree(source->right);

  p->setRightNode( pr );

  return p;

}

 

template<class T> void BinaryTree<T>::delete_tree(Tnode<T> * node)

{

 

 // 采用后序遍历,保证先删除子结点,再删除父结点

 if ( NULL != node )

 {

         delete_tree(node->left);

   delete_tree(node->right);

   delete node;

 }

 

}

template<class T>  

void BinaryTree<T>::insert(const T & t, Tnode<T> * current, Tnode<T> * parent, int flag)

{

     if ( NULL == t )

       return ;

  if ( NULL == root )

  {

    root = new Tnode<T>(t);

    return ;

  }

  if ( NULL == current )

  {

          Tnode<T> * p = new Tnode<T>(t);

    flag?( parent->left = p):(parent->right = p);

    return;

  }

  if( t<current->nodeValue)

   insert(t, current->left,current,1);

  else if (t>current->nodeValue)

   insert(t, current->right,current,0);

}

template<class T>  bool BinaryTree<T>::find(const T & t, Tnode<T> * current)

{

 if (NULL == current)

  return false;

 if (t == current->nodeValue)

  return true;

 else if (t < current->nodeValue)

       return find(t,current->left);

            else

             return find(t,current->right);

}

//main.cpp

 

#include <iostream>

#include "Tnode.h"

#include "BinaryTree.cpp"

#include <string>

using namespace std;

 

int main()

 {

  BinaryTree<int> binSearchTree;

  binSearchTree.insert(30);

  binSearchTree.insert(25);

  binSearchTree.insert(35);

  binSearchTree.insert(10);

  binSearchTree.insert(32);

  binSearchTree.insert(37);

  binSearchTree.insert(15);

  binSearchTree.level_order();

  bool b = binSearchTree.find( 10 );

  b?( cout << "exist/n" ):(cout << "does't exist/n");

  b = binSearchTree.find( 8 );

  b?( cout << "exist/n" ):(cout << "does't exist/n");

  return 0;

 }

 

 

 

 

 

 

 

 


 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值