使用c++构建一个二叉树

The binary tree is a fundamental data structure used in computer science. The binary tree is a useful data structure for rapidly storing sorted data and rapidly retrieving

stored data. A binary tree is composed of parent nodes, or leaves, each of which stores data and also links to up to two other child nodes (leaves) which can be visualized

spatially as below the first node with one placed to the left and with one placed to the right. It is the relationship between the leaves linked to and the linking leaf, also know

n as the parent node, which makes the binary tree such an efficient data structure. It is the leaf on the left which has a lesser key value (i.e., the value used to search for a le

af in the tree), and it is the leaf on the right which has an equal or greater key value. As a result, the leaves on the farthest left of the tree have the lowest values, whereas th

e leaves on the right of the tree have the greatest values. More importantly, as each leaf connects to two other leaves, it is the beginning of a new, smaller, binary tree. Due

to this nature, it is possible to easily access and insert data in a binary tree using search and insert functions recursively called on successive leaves. 

二叉树是计算机科学中的一种基本数据结构。它是一种非常有用的数据结构用于有序数据的快速储存和快速遍历。二叉树由父节点或者子叶组成,其中每一个都储存有数据,并且连接到另外两子节点(树叶), 这样的结构在空间上直观的表现为在第一个节点下面有一个位置存放左节点,一个位置存放右节点,是被连接的节点(子叶)和去连接别的节点的节点(父节点)之间的关系。这使得二叉树是一种高效的数据结构。二叉树左边的树叶数值总是存放较小的值,而右边的树叶总存放较大的值。因此,左边最底部树

叶的值是最小的,反之,右边最底部树叶的值是最大的。最重要的是,每个连接着另外两个节点的节点都是一个新二叉树的开始根节点,这使得使用搜索和插入函数通过递归

轻松访问二叉树的每一个树叶和插入数据到二叉树成为可能。

The typical graphical representation of a binary tree is essentially that of an upside down tree. It begins with a root node, which contains the original key value. The root 

node has two child nodes; each child node might have its own child nodes. Ideally, the tree would be structured so that it is a perfectly balanced tree, with each node 

having the same number of child nodes to its left and to its right. A perfectly balanced tree allows for the fastest average insertion of data or retrieval of data. The worst case

scenario is a tree in which each node only has one child node, so it becomes as if it were a linked list in terms of speed. The typical representation of a binary tree looks 

like the following:

二叉树最典型的图形化表示就是一个倒置的树,由根节点开始,其节点带一个键值。根节点有两个子节点,每个子节点可能又有自己的子节点,理想情况下,这棵树将被构造成一颗完全平衡二叉树,每一个左右子节点都有同等数目的子节点。完全平衡二叉树能够是插入数据和遍历数据有最小的平均时间复杂度,最糟糕的情况就是每一个节点只有

一个子节点,这就让这棵树的结构和链表一样的访问速度了,下面是一个典型二叉树的图形表示:

            10
 
           /    \
 
          6    14
          /  \     /   \
 
      5    8 11  18

The node storing the 10, represented here merely as 10, is the root node, linking to the left and right child nodes, with the left node storing a lower value than the parent node, and the node on the right storing a greater value than the parent node. Notice that if one removed the root node and the right child nodes, that the node storing the 

value 6 would be the equivalent a new, smaller, binary tree.

保存值为10的节点在这里就简单的用10表示,他是整棵树的跟节点,连接了一个左子树和一个右子树,左子树保存比其父节点的数,右子树保存比其父节点大的数。注意,如果我们移走了根节点和和其右子树,那么存储6的节点将成为一个新的,更小的树的根。

The structure of a binary tree makes the insertion and search functions simple to implement using recursion. In fact, the two insertion and search functions are also both very similar. To insert data into a binary tree involves a function searching for an unused node in the proper position in the tree in which to insert the key value. The insert 

function is generally a recursive function that continues moving down the levels of a binary tree until there is an unused leaf in a position which follows the rules of 

placing nodes. The rules are that a lower value should be to the left of the node, and a greater or equal value should be to the right. Following the rules, an insert function 

should check each node to see if it is empty, if so, it would insert the data to be stored along with the key value (in most implementations, an empty node will simply be a 

NULL pointer from a parent node, so the function would also have to create the node). If the node is filled already, the insert function should check to see if the key value 

to be inserted is less than the key value of the current node, and if so, the insert function should be recursively called on the left child node, or if the key value to be inserted 

is greater than or equal to the key value of the current node the insert function should be recursively called on the right child node. 

二叉树的结构使插入和查找简单的通过简单的递归就能实现,事实上,插入操作和搜索非常相似,在想二叉树插入数据的时候,就涉及到去查询一个在正确位置并且没有被使用的节点,然后才将值插入。插入函数是一个不断按指定规则向下面节点移动的递归函数,直到在正确位置找到一个没有被使用的节点,它的移动原则就是:相比某一个节点

较小的值应该放在改节点的左子节点,大于或者等于就放在有子节点。根据这个原则,插入函数应该检查每个节点是否为空,如果为空,那么插入值的存储应伴随一个新的节

点,(在大多数代码实现中,空节点用NULL指针表示,所以插入函数需要创建新的节点)。如果找到节点已经有了一个确切的值,那么插入函数就应该判断新插入的值是不是

比当前节点上的值小,如果新的值教小的话,那么函数就递归的调用函数去访问当前节点的子节点;如果新的值大于或者等于当前节点的值,那么就应该递归到有右子树,直

到找到一个合适的位置并插入。

The search function works along a similar fashion. It should check to see if the key value of the current node is the value to be searched. If not, it should check to see if the  value to be searched for is less than the value of the node, in which case it should be recursively called on the left child node, or if it is greater than the value of the node,  it should be recursively called on the right child node. Of course, it is also necessary to check to ensure that the left or right child node actually exists before calling the 

function on the node.

搜索函数和插入函数类似,它要判断当前节点的值对否和要搜索的值一致,如果不一致,那么就判断搜索的值比当前节点的值小,如果是,访问左节点的值继续做对比,否则访问右节点的值。当然,在递归中检查并保证访问的下一个左右子节点是存在的。


Because binary trees have log (base 2) n layers, the average search time for a binary tree is log (base 2) n. To fill an entire binary tree, sorted, takes roughly log (base 2) 

n * n. Let's take a look at the necessary code for a simple implementation of a binary tree. First, it is necessary to have a struct, or class, defined as a node.

因为二叉树有log(base 2) n层,所以搜索的平均时间复杂度是log(base 2) n。填充一整个有序的二叉树大致的时间复杂度是log(base 2) n * n. 让我们看看实现一个二叉树的核心代码,首先,应该构造一个结构体,或者一个类,定义为node:

struct node
{
  	int key_value;  
  	node *left;  
  	node *right;
};

The struct has the ability to store the key_value and contains the two child nodes which define the node as part of a tree. In fact, the node itself is very similar to the node in a linked list. A basic knowledge of the code for a linked list will be very helpful in understanding the techniques of binary trees. Essentially, pointers are necessary to

allow the arbitrary creation of new nodes in the tree.

定义的结构体应该能够存储节点的键值并且包含定义为树的一部分的两个子节点。实际上,节点本身和链表的节点非常相似。链表的基础知识对理解二叉树是非常有帮助的,为了能连给树创建意数量的节点,指针的的设置是必要的。


It is most logical to create a binary tree class to encapsulate the workings of the tree into a single area, and also making it reusable. The class will contain functions to

insert data into the tree and to search for data. Due to the use of pointers, it will be necessary to include a function to delete the tree in order to conserve memory after the

program has finished.

创建一个二叉树类来封装一棵树的操作室最符合逻辑的。并且同时使其具有复用性。类中应该包含插入函数和搜索函数,因为使用了指针,在程序完成工作后要使用删除函数释放内存。

class btree
{
public:        
	btree();        
	~btree();        
	void insert(int key);       
	node *search(int key);        
	void destroy_tree();    
private:        
	void destroy_tree(node *leaf);        
	void insert(int key, node *leaf);        
	node *search(int key, node *leaf);                
	node *root;
};

The insert and search functions that are public members of the class are designed to allow the user of the class to use the class without dealing with the underlying 

design. The insert and search functions which will be called recursively are the ones which contain two parameters, allowing them to travel down the tree. The 

destroy_tree function without arguments is a front for the destroy_tree function which will recursively destroy the tree, node by node, from the bottom up. 

The code for the class would look similar to the following:

Insert函数和search函数设置为类中的public方法,是为了让类的用户能更好的使用功能。含有两个参数的Insert函数和search函数将会被递归调用,从而实现从上到下访问这棵树。没有参数的destroy_tree函数是调用destroy_tree的前期步骤,含参destroy_tree函数将递归的从底部节点到跟节点一个一个的删除。代码如下:

btree::btree()
{
	root=NULL;
}

It is necessary to initialize root to NULL for the  later functions to be able to recognize that it does not exist.


初始化root为NULL使后面的函数能够判断根已经不存在是必要的。

btree::~btree()
{  
	destroy_tree();
}

The destroy_tree function will set off the recursive function destroy_tree shown below which will actually delete all nodes of the tree.


destroy_tree函数用来触发下面递归函数destroy_tree去删除树中的每一个节点

void btree::destroy_tree(node *leaf)
{
<span style="white-space:pre">	</span>if(leaf!=NULL)
  <span style="white-space:pre">	</span>{
 <span style="white-space:pre">		</span>destroy_tree(leaf->left);
   <span style="white-space:pre">		</span>destroy_tree(leaf->right);
<span style="white-space:pre">		</span>delete leaf;
<span style="white-space:pre">	</span>}
}

The function destroy_tree goes to the bottom of each part of the tree, that is, searching while there is a non-null node, deletes that leaf, and then it works its way back up. The function deletes the leftmost node, then the right child node from the leftmost node's parent node, then it deletes the parent node, and it continues this deletion 

working its way up to the node of the tree upon which delete_tree was originally called. In the example tree above, the order of deletion of nodes would be

5 8 6 11 18 14 10. Note that it is necessary to delete all the child nodes to avoid wasting memory.

destroy_tree函数从树的底部经过树的每一部分走到树的顶部。也就是说,搜索到每个非空的节点就删除这个节点,然后函数返回一层,函数在删除最左节点后然后就删除

最左节点的父节点的右子节点,然后才删除父节点,然后继续以同样的方式删除同一个父节点下的另外一个节点,然后又删除父节点,直到最后跟节点也没删除,例子中给

的数的删除顺序就是5 8 6 11 18 14 10. 删除树中每一个节点防止内存的浪费

void btree::insert(int key, node *leaf)
{
  if(key< leaf->key_value)
  {
    if(leaf->left!=NULL)
     insert(key, leaf->left);
    else
    {
      leaf->left=new node;
      leaf->left->key_value=key;
      leaf->left->left=NULL;    //Sets the left child of the child node to null
      leaf->left->right=NULL;   //Sets the right child of the child node to null
    }  
  }
  else if(key>=leaf->key_value)
  {
    if(leaf->right!=NULL)
      insert(key, leaf->right);
    else
    {
      leaf->right=new node;
      leaf->right->key_value=key;
      leaf->right->left=NULL;  //Sets the left child of the child node to null
      leaf->right->right=NULL; //Sets the right child of the child node to null
    }
  }
}

The case where the root node is still NULL will be  taken care of by the insert function that is nonrecursive and available to non-members of the class. The insert function searches, moving down the tree of children nodes, following the prescribed rules, left for a lower value to be inserted and right for a greater value, until it finds an empty 

node which it creates using the 'new' keyword and initializes with the key value while setting the new node's child node pointers to NULL. After creating the new node, 

the insert function will no longer call itself.

Root节点为NULL的情况将被insert函数考虑到,它并不是递归的,而且对于无成员的类也是有效的。Insert(带参数)函数向下查找没个节点时,遵循前面所说的那个规则

-----左边插入小的值,右边插入大的值,直到它找到一空节点,那么就创建一个新的节点保存键值并设置子节指向NULL,然后插入到空节点处,insert函数就停止递归。

node *btree::search(int key, node *leaf)
{
  if(leaf!=NULL)
  {
    if(key==leaf->key_value)
      return leaf;
    if(key<leaf->key_value)
      return search(key, leaf->left);
    else
      return search(key, leaf->right);
  }
  else return NULL;
}

The search function shown above recursively moves down the tree until it either reaches a node with a key value equal to the value for which the function is searching or until the function reaches an uninitialized node, meaning that the value being searched for is not stored in the binary tree. It returns a pointer to the node to the previous 

instance of the function which called it, handing the pointer back up to the search function accessible outside the class.

上面的search函数递归的从跟节点向下搜索这棵树,直到找到一个和目标值相同的值,或者遇到了没有初始化的节点,意味着这个树中并不存在要查询的目标值。函数返回一个指向节点的指针给前面实例对象调用它的函数,处理search函数返回的指针在类为是可行的。

void btree::insert(int key)
{
  if(root!=NULL)
    insert(key, root);
  else
  {
    root=new node;
    root->key_value=key;
    root->left=NULL;
    root->right=NULL;
  }
}

The public version of the insert function takes care of the case where the root has not been initialized by allocating the memory for it and setting both child nodes to NULL and setting the key_value to the value to be inserted. If the root node already exists, insert is called with the root node as the initial node of the function, and the recursive 

insert function takes over.

公共insert函数在发现root节点为NULL的时候会为其开辟内存并设置其两个子节点都为NULL,并将键值插入root节点,如果root节点已经存在,insert函数就会以root节点为

这个函数的初始节点递归的调用insert将节点插入完毕。

node *btree::search(int key)
{
  return search(key, root);
}

The public version of the search function is used to set off the search recursion at the root node, keeping it from being necessary for the user to have access to the root 

node.

公共函数search的作用是启动从树跟节点的递归搜索,通过它能够使用户的search(key, root)正常放问到根节点

void btree::destroy_tree()
{
  destroy_tree(root);
}
The public version of the destroy tree function is merely used to initialize the recursive destroy_tree function which then deletes all the nodes of the tree. 

共的destroy_tree函数同查找一样,用于启动destroy_tree(root)删除树中的所用节点。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值