【查找二叉树】清空、查找、插入、删除

查找二叉树:也叫排序二叉树,搜索二叉树。具有以下特点(百度百科)

二叉排序树或者是一棵空树,或者是具有下列性质的 二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于或等于它的 根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;

查找二叉树的创建和基本二叉树的创建无差异

二叉树的清空,实际上就是后序遍历删除

// 想要改变指针的值还是需要将他作为返回值,不然就是传入二级指针
static SearchTree MakeEmpty(SearchTree tree)
{
	if(tree){
		MakeEmpty(tree->LeftNode);
		MakeEmpty(tree->RightNode);
		free(tree);
		tree = NULL;
	}
	return tree;
}

查找二叉树的查找

1、基本二叉树的查找方法

// 实际上这样会将所有的节点都遍历一遍而忽略了查找二叉树的特点
// 以root为界限开始区分两者
static SearchTree FindNode(TreeElement element, SearchTree tree)
{
	SearchTree ret_tree = NULL;
	if (tree){
		if(element==tree->element){
			ret_tree = tree;
			return ret_tree;
		}
		
		ret_tree = FindNode(element, tree->LeftNode);
		ret_tree = FindNode(element, tree->RightNode);
	}
	return ret_tree;
}

2、二叉树的特点使用尾递归(递归在函数的尾部)

// 抓住了查找二叉树的特点,可以更加精确的进行查找
static SearchTree Find(TreeElement element, SearchTree tree)
{
	if(tree){
		if(tree->element==element){
			return tree;
		}else if(tree->element>element){
			return Find(element, tree->LeftNode);
		}else{
			return Find(element, tree->RightNode);
		}
	}
	return NULL;
}

3、将尾递归转换成赋值和goto语句

因为二叉树的平均深度是logN,所以使用的栈空间也只是logN,一般还是可以直接使用方法2,以下供参考

// 将尾递归转换成赋值和goto语句
static SearchTree FindNoLoop(TreeElement element, SearchTree tree)
{
next:
	if(tree){
		if(tree->element==element){
			return tree;
		}else{
			if(tree->element>element)
				tree = tree->LeftNode;
			else
				tree = tree->RightNode;
			goto next;
		}
	}
	return NULL;	
}

查找二叉树查找最大、最小值

static SearchTree FindMax(SearchTree tree)
{
next:
	if(tree){
		if(tree->RightNode == NULL)
			return tree;
		tree = tree->RightNode;
		goto next;
	}
	return tree;
}

static SearchTree FindMin(SearchTree tree)
{
	if(tree){
		if(tree->LeftNode == NULL)
			return tree;
		return FindMin(tree->LeftNode);
	}
	return NULL;
}

往二叉树中插入元素

如果插入的元素已经在二叉树中存在,则只是更新二叉树中记录发生频率的域(这里什么都不做)。否则插入到查找二叉树的尾部。

static SearchTree CreateTreeCell(TreeElement element)
{
	SearchTree tree = NULL;
	tree = (SearchTree)malloc(sizeof(*tree));
	if(tree==NULL){
		fprintf(stderr,"there is no space\n");
		return NULL;
	}
	tree->element= element;
	tree->RightNode = NULL;
	tree->LeftNode = NULL;
	return tree;
}
static SearchTree Insert(TreeElement element, SearchTree tree)
{
	if(tree){
		if(element>tree->element){
			if(tree->RightNode==NULL){
				tree->RightNode = CreateTreeCell(element);
			}else{
				Insert(element, tree->RightNode);
			}
		}else{
			if(tree->LeftNode==NULL){
				tree->LeftNode = CreateTreeCell(element);
			}else{
				Insert(element, tree->LeftNode);
			}
		}
		return tree;
	}
	return NULL;
}

这是书上的解法,比我的思路好。

static SearchTree InsertNode(TreeElement element, SearchTree tree)
{
	if(tree==NULL){
		
		tree = (SearchTree)malloc(sizeof(*tree));
		if(tree==NULL){
			fprintf(stderr,"there is no space\n");
			return NULL;
		}
		tree->element= element;
		printf("tree->element is %d\n", tree->element);
		tree->RightNode = NULL;
		tree->LeftNode = NULL;
	}else if(element>tree->element){
		//需要将返回值指向tree->RightNode
		tree->RightNode = InsertNode(element, tree->RightNode);
	}else{
		// 需要将返回值指向tree->LeftNode
		tree->LeftNode = InsertNode(element, tree->LeftNode);
	}
	return tree;
}

节点的删除

1)删除的节点为树叶

2)删除的节点包含一个子节点

3)删除的节点包含两个子节点(在该节点的右子树中寻找最小,特换为该节点元素,然后删除右子树元素最小的节点)

值得注意的:当两个指针同时指向同一块内存,free掉一个指针会导致另外一个指针成为野指针,所以也需要将其置为NULL

static SearchTree Delete(TreeElement element, SearchTree tree)
{
	if(tree){
		if(element>tree->element){
			// 无论是插入还是删除都需要建立指针的指向关系
			tree->RightNode = Delete(element, tree->RightNode);
		}else if(elementelement){
			tree->LeftNode = Delete(element, tree->LeftNode);
		}else{

			if(tree->RightNode!=NULL&&tree->LeftNode!=NULL){
				SearchTree tree_min = FindMin(tree->RightNode);
				if(tree_min){
					printf("tree->element is %d\n", tree->element);
					tree->element = tree_min->element;
					tree->RightNode = Delete(tree_min->element, tree->RightNode);
				}
			}else{
				SearchTree tree_temp = tree;
				if(tree->RightNode){
					tree = tree->RightNode;
				}else if(tree->LeftNode){
					tree = tree->LeftNode;
				}
				if(tree==tree_temp){//两个指针同时指向同一块内存,需要将其置为NULL
					tree = NULL;
				}
				free(tree_temp);
				tree_temp = NULL;
			}
		}
		return tree;
	}
}


你可能感兴趣的:(基础知识)