前面我们谈到了排序二叉树,还没有熟悉的同学可以看一下这个,二叉树基本操作二叉树插入二叉树删除1删除2删除3。但是排序二叉树也不是没有缺点,比如说,如果我们想在排序二叉树中删除一段数据的节点怎么办呢?按照现在的结构,我们只能一个一个数据查找验证,首先看看在不在排序二叉树中,如果在那么删除;如果没有这个数据,那么继续查找。那么有没有方法,可以保存当前节点的下一个节点是什么呢?这样就不再需要进行无谓的查找了。其实这样的方法是存在的,那就是在排序二叉树中添加向前向后双向节点。
    现在数据结构定义如下:

typedef struct _TREE_NODE
{
int data;
struct _TREE_NODE* prev;
struct _TREE_NODE* next;
struct _TREE_NODE* left;
struct _TREE_NODE* right;
}TREE_NODE;

拿节点的添加来说,我们可能需要添加prev、next的处理步骤。

void set_link_for_insert(TREE_NODE* pParent, TREE_NODE* pNode)
{
if(NULL == pParent || NULL == pNode)
return; if(pNode = pParent->left){
pNode->prev = pParent->prev;
if(pParent->prev)
pParent->prev->next = pNode;
pNode->next = pParent;
pParent->prev = pNode;
}else{
pNode->next = pParent->next;
if(pParent->next)
pParent->next->prev = pNode;
pNode->prev = pParent;
pParent->next = pNode;
} return;
} STATUS add_node_into_tree(TREE_NODE** ppTreeNode, int data)
{
TREE_NODE* pHead;
TREE_NODE* pNode; if(NULL == ppTreeNode)
return FALSE; if(NULL == *ppTreeNode){
*ppTreeNode = create_new_node(data);
return TRUE;
} if(NULL != find_data_in_tree(*ppTreeNode, data))
return FALSE; pHead = *ppTreeNode;
while(1){
if(data < pHead->data){
if(pHead->left){
pHead = pHead->left;
}else{
pNode = create_new_node(data);
pHead->left = pNode;
break;
}
}else{
if(pHead->right){
pHead = pHead->right;
}else{
pNode = create_new_node(data);
pHead->right = pNode;
break;
}
}
} set_link_for_insert(pHead, pNode);
return TRUE;
}

添加节点如此,删除节点的工作也不能马虎。

void set_link_for_delete(TREE_NODE* pNode)
{
if(pNode->prev){
if(pNode->next){
pNode->prev->next = pNode->next;
pNode->next->prev = pNode->prev;
}else
pNode->prev->next = NULL;
}else{
if(pNode->next)
pNode->next->prev = NULL;
}
} TREE_NODE* _delete_node_from_tree(TREE_NODE* root, TREE_NODE* pNode)
{
TREE_NODE* pLeftMax;
TREE_NODE* pLeftMaxParent;
TREE_NODE* pParent = get_parent_of_one(root, pNode); if(NULL == pNode->left && NULL == pNode->right){
if(pNode == pParent->left)
pParent->left = NULL;
else
pParent->right = NULL;
}else if(NULL != pNode->left && NULL == pNode->right){
if (pNode == pParent->left)
pParent->left = pNode->left;
else
pParent->right = pNode->left;
}else if(NULL == pNode->left && NULL != pNode->right){
if(pNode == pParent->left)
pParent->left = pNode->right;
else
pParent->right = pNode->right;
}else{
pLeftMax = get_max_node_of_one(pNode->left);
if(pLeftMax == pNode->left){
pNode->left->right = pNode->right;
if(pNode == pParent->left)
pParent->left = pNode->left;
else
pParent->right = pNode->left;
}else{
pLeftMaxParent = get_parent_of_one(root, pLeftMax);
pNode->data = pLeftMax->data;
pLeftMaxParent->right = NULL;
pNode = pLeftMax;
}
} return pNode;
} STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)
{
TREE_NODE* pNode;
TREE_NODE* pLeftMax;
TREE_NODE* pLeftMaxParent; if(NULL == ppTreeNode || NULL == *ppTreeNode)
return FALSE; if(NULL == (pNode = find_data_in_tree(*ppTreeNode, data)))
return FALSE; if(pNode == *ppTreeNode){
if(NULL == pNode->left && NULL == pNode->right)
*ppTreeNode = NULL;
else if(NULL != pNode->left && NULL == pNode->right)
*ppTreeNode = pNode->left;
else if(NULL == pNode->left && NULL != pNode->right)
*ppTreeNode = pNode->right;
else {
pLeftMax = get_max_node_of_one(pNode->left);
if(pNode->left == pLeftMax){
pNode->left->right = pNode->right;
*ppTreeNode = pNode->left;
}else{
pLeftMaxParent = get_parent_of_one(*ppTreeNode, pLeftMax);
pNode->data = pLeftMax->data;
pLeftMaxParent->right = NULL;
pNode = pLeftMax;
}
} goto final;
} pNode = _delete_node_from_tree(*ppTreeNode, pNode); final:
set_link_for_delete(pNode); free(pNode);
return TRUE;
}

其中,寻找最大值节点和寻找父节点的代码如下所示:

TREE_NODE* get_max_node_of_one(TREE_NODE* pNode)
{
if(NULL == pNode)
return NULL; while(pNode->right)
pNode = pNode->right; return pNode;
} TREE_NODE* get_parent_of_one(TREE_NODE* root, TREE_NODE* pNode)
{
if(NULL == root || NULL == pNode)
return NULL; while(root){
if(pNode == root->left || pNode == root->right)
return root;
else if(pNode->data < root->data)
root = root->left;
else
root = root->right;
} return NULL;
}

总结:
    (1)排序二叉树的序列化关键就是在二叉树节点添加前向指针和后继指针
    (2)排序二叉树是空间换时间的典型案例
    (3)排序二叉树是很多结构的基础,写多少遍都不为多,有机会朋友们应该多加练习
    (4)测试用例的编写是代码编写的关键,编写程序的目的就是为了消除bug,特别是低级bug

c++(排序二叉树线索化)的更多相关文章

  1. 数据结构之二叉树篇卷四 -- 二叉树线索化(With Java)

    一.线索二叉树简介 二叉树本身是一种非线性结构,然而当你对二叉树进行遍历时,你会发现遍历结果是一个线性序列.这个序列中的节点存在前驱后继关系.因此,如何将这种前驱后继信息赋予给原本的二叉树呢?这就是二 ...

  2. 记忆化搜索 codevs 2241 排序二叉树

    codevs 2241 排序二叉树 ★   输入文件:bstree.in   输出文件:bstree.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 一个边长为n的正三 ...

  3. 算法与数据结构(三) 二叉树的遍历及其线索化(Swift版)

    前面两篇博客介绍了线性表的顺序存储与链式存储以及对应的操作,并且还聊了栈与队列的相关内容.本篇博客我们就继续聊数据结构的相关东西,并且所涉及的相关Demo依然使用面向对象语言Swift来表示.本篇博客 ...

  4. 遍历二叉树 traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化

    遍历二叉树   traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化 1. 二叉树3个基本单元组成:根节点.左子树.右子树 以L.D.R ...

  5. 树和二叉树->线索二叉树

    文字描述 从二叉树的遍历可知,遍历二叉树的输出结果可看成一个线性队列,使得每个结点(除第一个和最后一个外)在这个线形队列中有且仅有一个前驱和一个后继.但是当采用二叉链表作为二叉树的存储结构时,只能得到 ...

  6. C++11 智能指针unique_ptr使用 -- 以排序二叉树为例

    用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...

  7. 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

    树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n ...

  8. c++(排序二叉树删除)

    相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写 ...

  9. c++(排序二叉树)

    前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点 ...

随机推荐

  1. 重启网络服务时 Bringing up interface eth0

    重启网络服务时报错:  Bringing up interface eth0: Error:Connection activation failed:Device not managed by Net ...

  2. Cleaner, more elegant, and harder to recognize (msdn blog)

    It appears that some people interpreted the title of one of my rants from many months ago, "Cle ...

  3. Effective Java 第三版——14.考虑实现Comparable接口

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  4. 房上的猫:JavaDoc注释

    //这是一个注释 /*   *这是一个演示程序   */ /**    *@这是JavaDoc注释.   */ JavaDoc注释 背景: javadoc是Sun公司提供的一个技术,它从程序源代码中抽 ...

  5. 80 行代码爬取豆瓣 Top250 电影信息并导出到 CSV 及数据库

    一.下载页面并处理 二.提取数据 观察该网站 html 结构 可知该页面下所有电影包含在 ol 标签下.每个 li 标签包含单个电影的内容. 使用 XPath 语句获取该 ol 标签 在 ol 标签中 ...

  6. ul li内的文字水平居中显示

    head><style rel="stylesheet" type="text/css" >#top{height:140px;}#top u ...

  7. 【Python3之正则re】

    一.正则re 1.正则表达式定义 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Pytho ...

  8. 【可持久化线段树】POJ2104 查询区间第k小值

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 61284   Accepted: 21504 Ca ...

  9. PE文件详解(四)

    本文转自小甲鱼的PE文件详解系列原文传送门 到此为止,小甲鱼和大家已经学了许多关于 DOS header 和 PE header 的知识.接下来就该轮到SectionTable (区块表,也成节表). ...

  10. Nginx常用配置实例(4)

    Nginx作为一个HTTP服务器,在功能实现方面和性能方面都表现得非常卓越,完全可以与Apache相媲美,几乎可以实现Apache的所有功能,下面就介绍一些Nginx常用的配置实例,具体包含虚拟主机配 ...