二叉树和排序

               
 
       
           
           
二叉树和排序
           
排序是算法中最典型的一类问题,也是显示计算机的特点的一类问题。在任何计算机算法课程中,都会先后给出几种著名的排序算法。二叉树排序是众多排序算法中很有趣的一个,随着排序二叉树的生成过程,整个排序任务也得到了完成。 
           
下图是两个简单的排序二叉树例子:
           
序列:3, 8, 1
           
排序二叉树:
           
3
           
//
           
/  /
           
1   8
           
 -------->
           
然后,按照上图中箭头的方向,从左到右依次读出树中的数字,就是排序的结果:1, 3, 8。
           
序列:7, 14, 9, 11, 5, 17
           
排序二叉树:
           
7
           
//
           
/  /
           
5       14
           
        //
           
        /  /
           
         9     17
           
  /
           
    /
           
  11
           
------------->
           
同样,按照上图箭头的方向,从左到右依次读数的结果为:5, 7, 9, 11, 14, 17。 
           
观察这些例子,可以验证排序二叉树的定义。排序二叉树的任何一个节点是:
           
  • 空节点或者,
  •                
  • 左子节点,数值,右子节点的组合,                
    • 其中左子节点,右子节点分别是一个排序二叉树;
    •                    
    • 所有左子节点二叉树中的数值<本节点的数值<所有右子节点二叉树中的数值。
    •                
  •            
根据这个定义,首先可以确定的是二叉树的数据结构,其实现如下: 
           
template<class T, int n, class U> struct Tree{
           
     typedef T Left;
           
     static const int value = n;
           
     typedef U Right;
           
}; 
           
整个排序过程,就是建立二叉树的过程,因此可以大致写出这个算法的思路:
           
  • 首先是简单情况平凡解,如果待排序序列为空,则返回一个空二叉树。
  •                
  • 普通情况下:                
    • 从序列中取出第1个元素;
    •                    
    • 然后将序列中剩余的元素建立成一排序二叉树;
    •                    
    • 最后,将第1个元素插入到此二叉树中。
    •                
  •            
这个算法叙述非常简单,但是其引入了一个新的关键问题——“插入”。在解决“插入”这个关键问题前,算法可实现如下: 
           
//算法定义
           
template<class NList> struct BuildSortTree;
           
//平凡解
           
template<> struct BuildSortTree<Empty>{
           
     typedef Empty Result;
           
};
           
//普通情况
           
template<class NList> struct BuildSortTree{
           
     typedef typename InsertToTree<
           
          NList::First,
           
          typename BuildSortTree<typename NList::Rest>::Result
           
     >::Result Result;
           
};
           
红色粗体表示引入的新“关键问题”,也就是将一个数值插入到某排序二叉树的算法。根据排序二叉树定义中的最后一点,可以描述如下:
           
  • 简单情况平凡解:若待插入二叉树为空,则返回形式为{空,数值,空}的二叉树;
  •                
  • 在普通情况下:
  •            
    • 若待插入元素小于根节点数值,则将其插入到左子树中;
    •                    
    • 反之,将此元素插入到右子树中。
    •                
根据这个叙述,此插入算法可以实现如下:
           
//定义
           
template<int n, class NTree> struct InsertToTree;
           
//平凡解
           
template<int n> struct InsertToTree<n, Empty>{
           
     typedef Tree<Empty, n, Empty> Result;
           
};
           
//普通情况
           
template<int n, class NTree> struct InsertToTree{
           
     template<bool x> struct If;
           
     template<> struct If<true>{
           
          typedef Tree<
           
              typename InsertToTree<n, typename NTree::Left>::Result,
           
              NTree::value,
           
              typename NTree::Right> Result;
           
     };
           
     template<> struct If<false>{
           
          typedef Tree<
           
              typename NTree::Left,
           
              NTree::value,
           
              typename InsertToTree<n, typename NTree::Right>::Result
           
              > Result;
           
     }; 
           
     typedef typename If< (n<NTree::value) >::Result Result;
           
}; 
           
为了验证算法的正确性,还需要一个能够打印出二叉树的程序,该程序从左到右依次扫描整棵树,凡节点为空则跳过,否则打印出节点的数值。其实现如下:
           
template<class NTree> struct PrintTree{
           
     static void print(){
           
          PrintTree<typename NTree::Left>::print();
           
          std::cout<<NTree::value<<", ";
           
          PrintTree<typename NTree::Right>::print();
           
     }
           
}; 
           
template<> struct PrintTree<Empty>{
           
     static void print(){}
           
}; 
           
写在main()函数中的测试代码为: 
           
typedef List<7, List<14, List<9,
           
List<11, List<5, List<17, Empty>>>>>> TestList;
           
PrintTree< BuildSortTree<TestList>::Result >::print(); 
           
程序输出排好的序列:5, 7, 9, 11, 14, 17。
           
Scheme 代码参考 
           
排序二叉树代码
           
(define-struct num-tree (left n right)) 
           
(define (insert-to-tree n atree)
           
  (cond
           
    [(empty? atree) (make-num-tree empty n empty)]
           
    [(< n (num-tree-n atree))
           
      (make-num-tree
           
        (insert-to-tree n (num-tree-left atree))
           
        (num-tree-n atree)
           
        (num-tree-right atree) )]
           
    [else
           
      (make-num-tree
           
        (num-tree-left atree)
           
        (num-tree-n atree)
           
        (insert-to-tree n (num-tree-right atree)) )]wink
           
(define (BST alon)
           
  (cond
           
    [(empty? alon) empty]
           
    [else (insert-to-tree (first alon) (BST (rest alon)) )]wink)  
           
           

 
 
 


网 易 Yeah.net 邮 箱 夏 日 大 变 脸,带 你 感 受 新 一 代 邮 箱 的 全 新 魅 力 >>              

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/yrryyff/article/details/87646641