`
java-mans
  • 浏览: 11427267 次
文章分类
社区版块
存档分类
最新评论

一步一步写算法(之排序二叉树线索化)

 
阅读更多

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】


前面我们谈到了排序二叉树,还没有熟悉的同学可以看一下这个,二叉树基本操作二叉树插入二叉树删除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#语言写的,试试看,相信给你好处的。

    数据结构和算法Flash动画演示

    一些算法的 flash动画演示:B树的删除,B树的生长过程,三元组表的转置,中序线索化二叉树,串的顺序存储,二分查找,二叉排序树的删除,二叉排序树的生成,二叉树的建立,克鲁斯卡尔算法构造最小生成树,冒泡排序,...

    数据结构和算法动画演示

    寻找中序线索化二叉树指定结点的前驱 寻找中序线索化二叉树指定结点的后继 构造哈夫曼树的算法模拟 构造哈夫曼树过程 树、森林和二叉树的转换 开放定址法建立散列表 拉链法创建散列表 朴素串匹配算法过程示意 图的...

    Flash动画演示 数据结构和算法

    中序线索化二叉树.swf 串的顺序存储.swf 二分查找.swf 二叉排序树的删除.swf 二叉排序树的生成.swf 二叉树的建立.swf 克鲁斯卡尔算法构造最小生成树.swf 冒泡排序.swf 分块查找.swf 单链表结点的删除.swf 单链表结点...

    【超全!】图解Java数据结构和算法(共195集)【资料+视频+课件+代码+笔记】

    稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫...排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找...

    数据结构与算法知识点.doc

    二叉树 5.1 二叉树概念、性质 5.2 完全二叉树概念、性质 5.3 满二叉树定义、性质 5.4 二叉树的遍历算法实现(递归与非递归)、线索二叉树的操作 5.5二叉搜索树概念及查找、插入、删除算法 5.6 AVL树概念;...

    c语言数据结构算法演示(Windows版)

    在二叉树线索化的过程中,图中指针 p 指向当前层二叉树的根结点,指针 pre 指向当前被访问的结点的前驱。在演示线索树的插入和删除过程时,图示窗口的下方还包括“输入行”和“提示行”。 18. 按先序序列建二叉链表...

    数据结构习题答案(全部算法)严蔚敏版

    6.4.3 中根次序线索化算法 6.4.4 在中根线索树上检索某结点的前趋或后继 6.4.5 在中根线索树上遍历二叉树 6.5 二叉树、 树和森林 6.5.1 树的存储结构 6.5.2 树与二叉树之间的转换 6.5.3 森林与二叉树的转换 ...

    数据结构各种算法实现(链表、队列、树、栈、串、)

    数据结构各种算法实现,有示例程序。 包括顺序表 单链表 双向链表 循环链表 顺序栈 链式栈 顺序队列 链式队列 串 二叉树 线索二叉树 堆 哈夫曼树 B+树 图 排序算法

    数据结构总结(自学、期末复习或考研备用).pdf

    第一章绪论、算法衡量指标、第二章线性表、顺序表、链表、第三章栈和队、栈、栈的应用举例、队列、循环队列、第四章串、串的模式匹配、第五章数组和广义表、稀疏矩阵的压缩存储方法:、广义表、第六章树和二叉树、...

    数据结构中C 语言源码及算法演示系统

    算法6.5是中序遍历线索二叉树的非递归算法,要对其源码进行测试,可首先调用算法6.6及6.7建立中序线索二叉树。以下是测试程序的源码,相关类型和辅助函数定义在文件include06.h和include06.cpp中,此略。

    数据结构讲义(严蔚敏版)(含算法源码).rar

    8. 线索二叉树 34 9. 树和森林 35 10. 赫夫曼树及其应用 36 二、 习题 37 第7章 图 39 一、 基础知识和算法 39 1. 图的有关概念 39 2. 图的存储结构 39 3. 图的遍历 42 4. 最小生成树 44 5. 拓扑排序 46 6. 关键路径...

    数据结构讲义(严蔚敏版)(含算法源码)

    知道线索二叉树,会对二叉树进行线索化 树、森林和二叉树的转化,会遍历树和森林 赫夫曼树及其应用 算法: 递归遍历二叉树及其应用(P) 构造赫夫曼树和赫夫曼编码(A) 树和二叉树的转换(A) 森林和二叉树的...

    java算法与数据结构

    (3)线索二叉树 (4)树的存储结构 (5)树、二叉树与森林的转化方法 (6)哈夫曼树 (7)二叉排序树及平衡化 (8)堆排序树 (9)B-树 4.图形结构 (1)图的定义及存储结构 (2)图的深度优先和广度优先遍历。 ...

    学习数据结构算法必备

     二叉树的线索化  先序遍历(Pre_order)  中序遍历(In_order)  后序遍历(Post_order) (2) 按先序建二叉树(CrtBT_PreOdr) (3) 线索二叉树  二叉树的线索化  生成先序线索(前驱或后继) (Pre_thre)  ...

    数据结构与算法

    线索二叉树 ………………………… 应用 …………………………………… 本章小结 …………………………………… 习题…………………………………………… 第 章 集合 ………………………………… 以集合为基础的抽象...

    严蔚敏 数据结构(C语言版) 代码 23490 书中算法

    5.3 遍历二叉树和线索二叉树 103 5.3.1 遍历二叉树 103 5.3.2 线索二叉树 109 5.4 树和森林 114 5.4.1 树的存储结构 114 5.4.2 森林与二叉树的转换 116 5.4.3 树和森林的遍历 116 5.5 赫夫曼树及其...

    数据结构各种算法实现(C++模板)

    数据结构各种算法实现(C++模板) 顺序表 单链表 双向链表 循环链表 顺序栈 链式栈 顺序队列 链式队列 优先级队列 串 二叉树 线索二叉树 堆 哈夫曼树 树 B+树 图 排序

    各种算法的flash演示

    B树的删除.rar B树的生长过程.rar 三元组表的转置.rar 中序线索化二叉树.rar 串的顺序存储.rar 二分查找.rar 二叉排序树的删除.rar 二叉排序树的生成.rar 二叉树的建立.rar 克鲁斯卡尔...

    C语言版数据结构与算法分析-严蔚敏经典视频教程

    06-005二叉树的前序、中序和后序遍历的递归与非递归算法 06-006统计二叉树中叶子结点个数、按给定的先序序列建立二叉链表 06-007线索链表的建立与遍历 06-008树的存储结构、森林和二叉树的转换、树和森林的遍历 06-...

Global site tag (gtag.js) - Google Analytics