Q27:二叉搜索树与双向链表

来源:互联网 发布:instabox 软件 编辑:程序博客网 时间:2024/06/07 03:30

Q:输入一颗二叉搜索树,将该二叉搜索树转换为一个排序的双向链表。要求不能创建任何新的结点。

分析:二叉搜索树的中序遍历就是一个有序的序列,而树的左孩子指针和有孩子指针当然就充当了前驱和后继指针,所以这种转换是自然的。

我们定义结构体如下:

struct TreeNode{int val;TreeNode *left;TreeNode *right;TreeNode(int v) : val(v),left(0),right(0){}};

回想中序遍历的模板:

void InOrderVisit(TreeNode *root){if(!root) return;InOrderVisit(root->left);visit(root);InOrderVisit(root->right);}

 该题目中,visit函数显然不是仅仅打印出这个值这么简单,但其实质还是一样的,既然中序访问各个节点的顺序是有序的,那么我们只需要将访问到的结点挂在到一个双向链表上就可以,想想我们创建一个双向链表的过程,在链表的表尾,创建新的结点,将其与表尾的结点连接,由于不允许我们使用额外的结点,所以这里就要求我们判断链表头结点是否为空的情况。若没有这个限制,像我们在进行链表的操作的时候,为了统一操作,我们总是会创建一个只起到统一操作的表头节点,其中不包含任何有用信息。

那么现在我们设计下我们程序的大体流程,以及需要哪些参数。

首先,我们要不停的修改双向链表,所以要有一个二级指针,或者是一级指针的引用,这里我们选择使用引用&。

接下来,在visit功能块里,我们把访问的结点挂到链表的表尾。

因为是双向的,所以即使我们只记录链表尾结点,通过循环向前寻找,我们是可以得到链表的表头的。

void TreeToLink(TreeNode *root,TreeNode *&linkTail){if(!root) return ;        //handle its left_sub_treeTreeToLink(root->left,linkTail);        //similar to visit()        //handle the first node        if(linkTail == NULL)linkTail = root;else{linkTail->right = root;root->left = linkTail;        linkTail = root;}        //handle its right_sub_treeTreeToLink(root->right,linkTail);}

最终,我们得到的linkTail是一个尾结点,我们可以通过left指针域向前遍历,得到头,至此,问题就解决了。

总结:

这类的问题很多,但都有一个共性,就是他们都是三种递归遍历的变种,不同的是visit的处理,但都可以套用模板。

参考书里给出的解法也不错,但个人觉得有点麻烦,既然有模板,我们还是推荐套用模板,就像我们高考时的作文,自己熟练掌握几套模板总是很受用的,所谓万变不离其踪。


1 0
原创粉丝点击