二叉树和排序
排序是算法中最典型的一类问题,也是显示计算机的特点的一类问题。在任何计算机算法课程中,都会先后给出几种著名的排序算法。二叉树排序是众多排序算法中很有趣的一个,随着排序二叉树的生成过程,整个排序任务也得到了完成。
下图是两个简单的排序二叉树例子:
序列: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;
};
整个排序过程,就是建立二叉树的过程,因此可以大致写出这个算法的思路:
这个算法叙述非常简单,但是其引入了一个新的关键问题——“插入”。在解决“插入”这个关键问题前,算法可实现如下:
//算法定义
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)) )])
(define (BST alon)
(cond
[(empty? alon) empty]
[else (insert-to-tree (first alon) (BST (rest alon)) )])
|
网 易 Yeah.net 邮 箱 夏 日 大 变 脸,带 你 感 受 新 一 代 邮 箱 的 全 新 魅 力 >>