本文简单简介二叉树的概念,并给出平衡一颗二叉树的方法

关于二叉树
    现在有N个元素的数组或者链表,要查找一个元素必须遍历数组直到找到元素。假如元素在是数组中最后一个或者数组中不存在这样的元素,那么很不幸,我们要遍历整个数组。如果N非常大,那将是非常痛苦的一件事情。
用二叉树情况就好多了:
1. 更快的查找
2. 增加元素时,元素被自动排列
原理:
在链表或数组中,元素一个接着一个,如图


 

在二叉树中情况不太一样了


每个元素连着两个元素,左孩子和右孩子。他们存储的值的关系有如下规定
Valueleft<Valuemiddle<=Valueright

排序:
在二叉树中利用递归你能很方便的排序
前序遍历
PrintElement(pTopMostElement)
   .
   .
  
void PrintElement(TreeElement* pElement)
  
{
    
if (pElement)
    
{
      PrintElement(pElement
->LeftChild)
      pElement
->PrintMe()
      PrintElement(pElement
->RightChild)
    }

  }

后序遍历:

PrintElementReversed(pTopMostElement)
   .
   .
  
void PrintElementReversed(TreeElement* pElement)
  
{
    
if (pElement)
    
{
      PrintElementReversed(pElement
->RightChild)
      pElement
->PrintMe()
      PrintElementReversed(pElement
->LeftChild)
    }

  }


如何使二叉树平衡?
添加元素的顺序将影响二叉树的形态,以3,6,4,8,1,9,2,7,5的顺序得到

1,2,3,4,5,6,7,8,9将得到

有以下方法可以考虑:
1. 以非排序的元素插入元素,不能要求给出的元素是高度不排序的
2. 以一组随机元素构造二叉树,然后替换这些元素,然后通过旋转得到平衡的树。参考随机树。
3. 重构这稞树

重构整稞树
1. 把元素拷贝到数组中,以升序排序
2. 清空这棵树
3. 从数组中高度不排序的选取元素插入树中可以这样完成第三步:


可以递归的实现:
// Assuming array ranges from [0..arraySize-1]
GetFromOrderedArray(0,arraySize-1)
  .
  .
void GetFromOrderedArray(int lowBound,int highBound)
{
  
if (hi < low) return;
  middlePos 
= lowBound+(highBound-lowBound)/2
  
// middlePos is now at the element in the middle
  
// between lowBound and highBound, so we just add
  
// it to the tree

  AddElement ( theOrderedArray[middlePos] )

  
// Pick the middle one "to the left"
  AddFromOrderedArray(lowBound,middlePos-1)

  
// Pick the middle one "to the right"
  AddFromOrderedArray(middlePos+1,highBound)
}



删除一个元素

首先要找到要删除的元素E,有两种方法:
1. 通过遍历找到这个元素E
2. 给每个元素一个指向双亲的指针

接下来就是删除的过程了:
1. 剪断E与他双亲的连接
2. 将左右孩子所在的子树同其他元素一样加到树中
3. 删除E

void RemoveElement(TreeElement* theOneToRemove)
{
  TreeElement
* pParent = theOneToRemove->GetParent();

  
// Ok, so it has a parent, then we'll simply just disconnect it.
  if (pParent)
  
{
     
if (pParent->GetLeftChild() == theOneToRemove)
     
{
        pParent
->SetLeftChild(NULL);
     }

     
else
     
{
        ASSERT(pParent
->GetRightChild() == theOneToRemove);
        pParent
->SetRightChild(NULL);
     }

  }

  
else
  
{
     
// No parent? Then we're removing the root element.
     theTopMostElement = NULL;
   }


  
// Disconnected, now we reconnect its children (if any)
  
// just by adding them as we add any other node.
  if (theOneToRemove->GetLeftChild())
   AddElement(theOneToRemove
->GetLeftChild());
  
if (theOneToRemove->GetRightChild())
   AddElement(theOneToRemove
->GetRightChild());

  
//Zap the element (if that's what you want to do)
  delete theOneToRemove;

}


注解:

通过函数回调 遍历二叉树

注:函数回调例如AddElement(theOneToRemove->GetRightChild());

简而言之,回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。

                                            #内容选自CodeGuru
若理解错误,欢迎指正!