二叉搜索树的建立、查找、删除等相关操作实现及对于删除操作的详细解释

前记,最近开始了保研准备,故记录一下复习过程。

这次就对二叉树做一下实现。

在以下操作中,稍复杂的应该是删除,本想采用递归的方式构造删除函数,奈何最后还是按照自己的想法写了,本博客将对我的实现稍作描述,如有错误请指正,实现的方法中肯定也有很多累赘之处,也请多多指出。

首先将所有的情况分为三种:

  • 被删除的节点没有儿子节点,对应(1)。
  • 被删除的节点有一个儿子节点,此时只需要将儿子节点上移至原有的节点处,对应(2)。
  • 被删除的节点有两个儿子节点,此时可以选择左子树的最大值或者右子树的最小值对应的节点代替原有被删除的节点,对应(3)。

其中,第一种情况可以视为特殊的第二种情况,可以合并为第二种情况。实现时只需要记住被删除节点的父节点(parentNode)以及被删除节点相对于父节点的位置即可,在这里用flag表示,flag为0代表被删除节点是父节点的左儿子。

而第三种情况下,我选择的是寻找被删除节点右子树的最小值,并将情况分为了以下两种情况:

  • 情况(1)的特点是,被删除节点的右子树仅为一个节点,在这种情况下只需要将被删除节点对应的data修改为右子树的data(22)即可。
  • 情况(2)即除(1)外其他情况

下面对情况(2)进行分析:

pTemp指向被删除节点(但在下面的程序中是pTemp2)

p指向经过寻找以后最终找到的右子树最小值对应节点

parentNode指向最小值对应节点的父节点

首先,我们用最小值节点代替被删除节点的位置,那么这意味着这个最小值节点的子树会受到影响,我们需要找到他们未来应该接到哪里。

被删除节点的代替可以直接用赋值实现

pTemp->data = p->data;

因为最小值节点(上图节点19)一定是这棵树的最左的儿子,因此它没有左儿子,只可能有右儿子。我们只需要考虑这个节点的右子树应该放在哪里,经过观察与大小比较,我们可以发现这个最小值节点的右子树未来应该接在这个节点的父节点(parentNode,上图22)的左儿子处。

于是有

parentNode->left = p->right;

最后只要释放掉最小值对应节点即可。

free(p)

详细的代码如下:

#include<iostream>
#include<stdlib.h>

#include <cstdlib>
#include <stdio.h>

typedef struct TreeNode {
   struct TreeNode* left;
   struct TreeNode* right;
   int data;

}TreeNode, * TreeP;
using namespace std;
TreeP findMin(TreeP root);
TreeP insertNode(TreeP root, int val) {
   TreeP pTemp = NULL;

   if (!root) {
   	root = (TreeNode*)malloc(sizeof(TreeNode));
   	//root = new TreeNode();
   	root->data = val;
   	root->left = NULL;
   	root->right = NULL;
   	return root;
   }
   else {
   	TreeP p = root;
   	while (p) {
   		pTemp = p;
   		if (val < p->data) {
   			p = p->left;
   		}
   		else if (val > p->data) {
   			p = p->right;
   		}

   	}
   	TreeP tNode = (TreeNode*)malloc(sizeof(TreeNode));
   	tNode->data = val;
   	tNode->left = NULL;
   	tNode->right = NULL;
   	if (pTemp->data > val) {
   		pTemp->left = tNode;
   	}
   	else {
   		pTemp->right = tNode;
   	}

   	return root;

   }

}

//删除,共有三种情况
bool deleteNode(TreeP root, int val) {
   TreeP p = root, parentNode = root,pTemp2 = NULL;
   int flag = -1;
   //找到要删除的节点
   if (!p) {
   	return false;
   }

   while (p) {
   	;
   	if (p->data == val) {
   		break;
   	}
   	else if (p->data > val) {
   		parentNode = p;
   		p = p->left;
   		flag = 0;
   	}
   	else if (p->data < val) {
   		parentNode = p;
   		p = p->right;
   		flag = 1;
   	}

   }
   if ( !p->right) {

   	if (!flag) {
   		parentNode->left = p->left;

   	}
   	else {
   		parentNode->right = p->left;
   		//p = p->left;
   	}
   	free(p);
   }
   else if (!p->left) {
   	if (!flag) {
   		parentNode->left = p->right;
   	}
   	else {
   		parentNode->right = p->right;
   	}
   	free(p);
   }
   //如果有两个节点
   else {
   	pTemp2 = p;
   	parentNode = p;
   	//找到右子树上最小的值
   	p = p->right;

   	while (p->left) {
   		parentNode = p;
   		p = p->left;
   	}

   	pTemp2->data = p->data;

   	if (pTemp2 == parentNode) {
   		parentNode->right = NULL;
   	}
   	else {
   		parentNode->left = p->right;
   	}

   	free(p);
   }

   return true;

}

TreeP findMin(TreeP root) {

   if (root) {
   	if (root->left == NULL) {
   		return root;
   	}
   	findMin(root->left);
   }
   else {
   	return root;
   }

}

TreeP findMax(TreeP root) {

   if (root) {
   	if (root->right == NULL) {
   		return root;
   	}
   	findMin(root->right);
   }
   else {
   	return root;
   }

}

TreeP findParentNode(TreeP root, TreeP node) {
   if (root) {
   	if (root->left == node || root->right == node) {
   		return root;
   	}
   	findParentNode(root->left,node);
   	findParentNode(root->right,node);
   }
   else {
   	return root;
   }

}

TreeP findNode(TreeP root, int val) {
   TreeP p = root;
   if (p) {
   	if (p->data == val) {
   		return p;
   	}
   	findNode(p->left, val);
   	findNode(p->right, val);
   }
}

void travelPreOrder(TreeP p) {
   if (p) {
   	cout << p->data << " ";
   	travelPreOrder(p->left);
   	travelPreOrder(p->right);
   }

}

int main() {

   TreeP p = NULL;
   int val = 0;
   int num;
   cin >> num;
   while (num > 0) {
   	cin >> val;
   	p = insertNode(p, val);
   	num--;
   }

   travelPreOrder(p);
   cout << endl;
   p = findNode(p, 18);
   cout << p->data<< endl;

}

原文地址:https://www.cnblogs.com/yuyuan-bb/p/12589971.html

时间: 2024-10-14 19:33:38

二叉搜索树的建立、查找、删除等相关操作实现及对于删除操作的详细解释的相关文章

二叉搜索树的建立

二叉搜索树最大特征是:左边子结点的值<当前结点的值,右边子结点的值>当前结点的值. 依照这个特征,可以使用递归和非递归两种方式建立一颗二叉搜索树. 下面是我的代码,分明列举了递归和非递归的建立方式.最初写的代码与正确版本大致相同,但程序总是运行不通过,debug后发现问题在于指针操作错误.自以为对c语言非常熟稔了,但还是犯下如此幼稚的错误,所以贴出这个错误,作为一个警示. 2014/5/24 ps:原来二叉搜索树最难的地方在于删除操作,所以补充一个删除操作.此外,还明白了书本介绍二叉搜索树的原

二叉搜索树的创建 &amp;&amp; 查找 &amp; 插入 &amp; 删除

二叉搜索树的删除: 在删除之前需要从树中查找到这个节点,然后再针对情况来判断如何删除. 分为三种情况,首先是此节点没有孩子节点,此节点有一个孩子节点,此节点有两个孩子节点 void Delete(BinTree*& root,int value) { BinTree* delnode= NULL; if(root == NULL) return ; BinTree* temp = root; BinTree* parent =NULL; while(temp!=NULL) { if(temp-&g

【数据结构】5.2 二叉搜索树的创建查找以及插入操作

TAG 此代码遇到一个bug,在Insert函数中,注释部分,思考一下为什么用这个方法来添加会失效 #include<iostream> using namespace std; struct BTNode { int data; BTNode *lchild,*rchild; }; void selectsort(int a[], int n) { for (int i = 1; i < n; i++) { for (int j = i + 1; j < n; j++) { if

题目1009:二叉搜索树(二叉搜索树的建立)

题目链接:http://ac.jobdu.com/problem.php?pid=1009 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: // // 1009 二叉搜索树.cpp // Jobdu // // Created by PengFei_Zheng on 09/04/2017. // Copyright © 2017 PengFei_Zheng. All rights reserved. // #include <stdi

PHP 二叉查找树(二叉搜索树)的查找

如下图:在二叉查找树中,搜索节点19是否存在 代码实现: 测试结果: 原文地址:https://www.cnblogs.com/qiangqiangge/p/12283930.html

二叉搜索树的查找

---------------------siwuxie095 二叉搜索树的查找 程序:二叉搜索树和顺序查找表的查找对比 FileOps.h: #ifndef FILEOPS_H #define FILEOPS_H #include <string> #include <iostream> #include <fstream> #include <vector> using namespace std; namespace FileOps { int fir

二叉搜索树的插入,删除,和中序遍历

构建一个值的类型为int的二叉搜索树,输入N和M,然后进行N次插入操作,每次插入之后进行一次遍历验证代码正确性.然后进行M次删除操作,每次删除之后进行一次遍历验证代码正确性. #include "bits/stdc++.h" using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; struct BST { int value; BST* lson; BST* rson; }* root; void r

C++实现二叉搜索树的常用操作

实现操作 (1)二叉搜索树的建立 (2)二叉搜索树的插入 (3)二叉搜索树的三种递归遍历(前序.中序和后续) (4)二叉搜索树的三种非递归遍历(前序.中序和后续) (5)二叉搜索树的逐层打印 (6)搜索某一个字符(递归算法) (7)搜索一个字符(非递归算法) (8)查找最大元素 (9)查找最小元素 有时间再实现: (10)二叉搜索树的前驱和后继查找 (11)二叉搜索树的删除 源码分析: #include <iostream> #include <stack> #include &l

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int