二叉树(查询和删除)
来源:互联网 发布:js在win7下不能运行 编辑:程序博客网 时间:2024/06/14 02:19
一,插入数据
二叉树的插入过程
数据结构
typedef struct TreeNode { int data; struct TreeNode *leftchild; struct TreeNode *rightChild; struct TreeNode *parent;}TreeNode;
1, 第一步判断二叉树是否有根节点
//判断根节点是否为空 if (root == NULL) { //创建根节点 root = (TreeNode *)malloc(sizeof(TreeNode)); //赋值 root->data = data; root->leftchild = NULL; root->rightChild = NULL; return root; }
2, 如果有节点就记录当前的根节点,遍历比较节点的数据大小, 添加节点
//遍历比较 TreeNode *parent = NULL; TreeNode *node = root; //遍历遍历比较大小 , 查询找到插入的位置 for (; node != NULL; ) { parent = node; //比较值 if (data < parent->data) node = parent->leftchild; else if (data > parent->data) node = parent->rightChild; else return node; } //创建节点 TreeNode* newNode = (TreeNode *)malloc(sizeof(TreeNode)); //赋值操作 newNode->data = data; newNode->leftchild = NULL; newNode->rightChild = NULL; if (data < parent->data) { parent->leftchild = newNode; } else { parent->rightChild = newNode; } //child指针父节点parent newNode->parent = parent;
二,前序,中序, 后续遍历
提一下遍历的定义:
- 前序遍历: DLR , 先根,在左, 再右
- 中序遍历:LDR,先左,在根, 再右
- 后序遍历:LRD, 先左, 在右,在根
前序遍历
LRD
void modleOrderTraverse(TreeNode *node) { if (node == NULL) return; printf("%d\t", node->data); modleOrderTraverse(node->leftchild); modleOrderTraverse(node->rightChild);}
中序遍历
LDR
void midOrderTraverse(TreeNode* node) { if (node == NULL) return; midOrderTraverse(node->leftchild); printf("%d\t", node->data); midOrderTraverse(node->rightChild);}
后序遍历
若二叉树为空则结束返回,
否则:
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根结点
LRD
void maxOrderTraverse(TreeNode* node) { if (node == NULL) return; midOrderTraverse(node->leftchild); midOrderTraverse(node->leftchild); printf("%d\t", node->data);}
三,删除一个节点的操作
删除一个节点分为: 四种情况
1. 没有左右孩子节点的树的情况
2. 有左孩子的节点的树的情况
3. 有右孩子的节点的树的情况
4. 有左右孩子的节点的树的情况
1,第一种情况的分析没有左右节点的树情况
可以分为两种情况
- 是根(root)节点情况
- 不是节点的情况, 是叶子节点情况
①是根节点的情况图
//父节点为空时if (parent == NULL) { root = NULL; //置空 }
②,不是根节点的情况是叶子结点情况
if (parent->leftchild == node) { parent->leftchild = node->rightChild; } else if (parent->rightChild == node) { parent->rightChild = node->leftchild; }
二,第二种情况和第三情况
只有左孩子或者右孩子的节点
大致也分为两类
1. 是根节点
2. 不是根节点,是只有左孩子或者右或者情况的节点
①,是根(root)节点的情况
//判r断父节点if (parent == NULL) { root = parent->leftchild;}
②,不是根节点的情况,只有左孩子或者右或者情况的节点
实现:
if (parent->leftchild == node) { parent->leftchild = node->leftchild; } else if (parent->rightChild == node) { parent->rightChild = node->leftchild; }
三,第四情况
分为两个大的情况
- 节点right节点的left为空的情况(node->rightChild->left == NULL)
- 节点的right节点的left不为空的情况(node->rightCild->left != NULL)
①,第一种情况 (node->rightChild->left == NULL)
在这种情况下面也分为两种情况
1. 是根节点
2. 不是根节点,是只有左孩子或者右或者情况的节点
if (parent->rightChild->leftchild == NULL) { node->rightChild->leftchild = node->rightChild; if (parent == NULL) { root = node->rightChild; } else if (parent->leftchild == node) { parent->leftchild = node->leftchild; //parent->leftchild->rightChild = node->rightChild; } else if (parent->rightChild == node) { parent->rightChild = node->leftchild; //parent->rightChild->leftchild = node->rightChild; } }
②第二种情况(node->rightChild->leftChild != NULL)
TreeNode *leftNode = MinTreeNode(node->rightChild); //第一步 leftNode->leftchild = node->leftchild; //第二步 TreeNode* leftNodep = leftNode->parent; leftNodep->leftchild = leftNode->rightChild; //第三步 leftNode->rightChild = node->rightChild; //第四步 if (parent == NULL) root = leftNode; else { if (parent->leftchild == node) parent->leftchild = leftNode; else if (parent->rightChild == node) parent->rightChild = leftNode; //leftNode->parent = parent; } }
C语言的代码实现
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>typedef struct TreeNode { int data; struct TreeNode *leftchild; struct TreeNode *rightChild; struct TreeNode *parent;}TreeNode;//根节点TreeNode *root = NULL;//添加节点TreeNode* put(int data) { //判断根节点是否为空 if (root == NULL) { //创建根节点 root = (TreeNode *)malloc(sizeof(TreeNode)); //赋值 root->data = data; root->leftchild = NULL; root->rightChild = NULL; return root; } //遍历比较 TreeNode *parent = NULL; TreeNode *node = root; //遍历遍历比较大小 ,查询找到插入的位置 for (; node != NULL; ) { parent = node; //比较值 if (data < parent->data) node = parent->leftchild; else if (data > parent->data) node = parent->rightChild; else return node; } //创建节点 TreeNode* newNode = (TreeNode *)malloc(sizeof(TreeNode)); //赋值操作 newNode->data = data; newNode->leftchild = NULL; newNode->rightChild = NULL; if (data < parent->data) { parent->leftchild = newNode; } else { parent->rightChild = newNode; } //child指针父节点parent newNode->parent = parent; return newNode;}/*** 中序遍历*/void midOrderTraverse(TreeNode* node) { if (node == NULL) return; midOrderTraverse(node->leftchild); printf("%d\t", node->data); midOrderTraverse(node->rightChild);}/*** 后序遍历*/void maxOrderTraverse(TreeNode* node) { if (node == NULL) return; midOrderTraverse(node->leftchild); midOrderTraverse(node->leftchild); printf("%d\t", node->data);}/*前序遍历*/void modleOrderTraverse(TreeNode *node) { if (node == NULL) return; printf("%d\t", node->data); modleOrderTraverse(node->leftchild); modleOrderTraverse(node->rightChild);}TreeNode * MinTreeNode(TreeNode *node) { if (node == NULL) { printf("方法名:%s\n", __FUNCTION__); return NULL; } else { while (node->leftchild != NULL) { node = node->leftchild; } return node; }}/* 删除一个节点*/void delNode(TreeNode *node) { if (node == NULL) { printf("node == null\n"); } else { TreeNode *parent = node->parent; //1, 没有孩子 if ((node->rightChild == NULL) && (node->leftchild == NULL)) { //父节点为空时 if (parent == NULL) { root = NULL; } else { if (parent->leftchild == node) { parent->leftchild = node->rightChild; } else if (parent->rightChild == node) { parent->rightChild = node->leftchild; } } //释放节点的内存 free(node); //节点数据置空 node->data = NULL; //父指针 node->parent = NULL; node = NULL; } else if ((node->rightChild == NULL) && (node->leftchild != NULL)) { //2, 有左孩子 //判r断父节点 if (parent == NULL) { root = parent->leftchild; } else { if (parent->leftchild == node) { parent->leftchild = node->leftchild; } else if (parent->rightChild == node) { parent->rightChild = node->leftchild; } } //释放节点的内存 free(node); //节点数据置空 node->data = NULL; //父指针 node->parent = NULL; node = NULL; } else if ((node->rightChild != NULL) && (node->leftchild == NULL)) { //3, 有右孩子 //判断父节点 if (parent == NULL) { root = parent->rightChild; //parent->rightChild->parent = NULL; } else { if (parent->leftchild == node) { parent->leftchild = node->rightChild; } else if (parent->rightChild == node) { parent->rightChild = node->rightChild; } } //释放节点的内存 free(node); //节点数据置空 node->data = NULL; //父指针 node->parent = NULL; node = NULL; } else if ((node->rightChild != NULL) && (node->leftchild != NULL)) { //4, 有左右孩子 if (parent->rightChild->leftchild == NULL) { node->rightChild->leftchild = node->rightChild; if (parent == NULL) { root = node->rightChild; } else if (parent->leftchild == node) { parent->leftchild = node->leftchild; //parent->leftchild->rightChild = node->rightChild; } else if (parent->rightChild == node) { parent->rightChild = node->leftchild; //parent->rightChild->leftchild = node->rightChild; } } else { TreeNode *leftNode = MinTreeNode(node->rightChild); //第一步 leftNode->leftchild = node->leftchild; //第二步 TreeNode* leftNodep = leftNode->parent; leftNodep->leftchild = leftNode->rightChild; //第三步 leftNode->rightChild = node->rightChild; //第四步 if (parent == NULL) root = leftNode; else { if (parent->leftchild == node) parent->leftchild = leftNode; else if (parent->rightChild == node) parent->rightChild = leftNode; //leftNode->parent = parent; } } //释放节点的内存 free(node); //节点数据置空 node->data = NULL; //父指针 node->parent = NULL; node = NULL; } }}TreeNode* searchNode(int data) { if (root == NULL) { return NULL; } TreeNode* node = root; while (node != NULL) { if (node->data == data) { return node; } else if (node->data < data) { node = node->rightChild; } else if (node->data > data) { node = node->leftchild; } } return NULL;}int main(int argc, char* argv[]){ int arrays[] = {12, 3, 23, 5, 8, 1, 19, 2, 4, 56, 45, 34, 23, 33}; for (int i = 0; i < 14; i++) put(arrays[i]); printf("中序遍历\n"); midOrderTraverse(root); printf("\n"); printf("前序遍历\n"); printf("\n"); modleOrderTraverse(root); printf("\n"); printf("后序遍历\n"); printf("\n"); maxOrderTraverse(root); TreeNode * del = searchNode(33); delNode(del); printf("\n"); midOrderTraverse(root); //modleOrderTraverse(root); printf("\n"); system("pause"); return EXIT_SUCCESS;}
Java代码的实现
package com.songli.BinarayTree;import java.util.NoSuchElementException;import com.sun.jmx.snmp.BerException;/** > Author: songli > QQ: 2734030745 > Mail: 15850774503@163.com > CSDN: http://my.csdn.net/Poisx > github: https://github.com/chensongpoixs */public class SearchBinaryTree { //根节点 public TreeNode root; public class TreeNode { int data; TreeNode leftChild; TreeNode rightChild; TreeNode parent; /** * @return the data */ public int getData() { return data; } /** * @param data the data to set */ public void setData(int data) { this.data = data; } /** * @return the leftChild */ public TreeNode getLeftChild() { return leftChild; } /** * @param leftChild the leftChild to set */ public void setLeftChild(TreeNode leftChild) { this.leftChild = leftChild; } /** * @return the rightChild */ public TreeNode getRightChild() { return rightChild; } /** * @param rightChild the rightChild to set */ public void setRightChild(TreeNode rightChild) { this.rightChild = rightChild; } /** * @return the parent */ public TreeNode getParent() { return parent; } /** * @param parent the parent to set */ public void setParent(TreeNode parent) { this.parent = parent; } /** * 构造器 * @param data * @param leftChild * @param rightChild * @param parent */ public TreeNode(int data) { super(); this.data = data; this.leftChild = null; this.rightChild = null; this.parent = null; } } public TreeNode getRoot() { return root; } /** * 添加节点 * @param data * @return */ public TreeNode put(int data) { //判断根节点是否为空 if (root == null){ //创建节点 TreeNode node = new TreeNode(data); //赋值给根节点 root = node; return node; //返回节点 } //遍历比较 TreeNode parent = null; //得到根节点 TreeNode node = root; //遍历比较节点的大小 for (; node != null; ) { parent = node; //比较当前节点的值 if (data < node.data) { node = node.leftChild; } else if(data > node.data) { node = node.rightChild; } else { //相等情况返回 return node; } } //添加节点 TreeNode newNode = new TreeNode(data); if (data < parent.data) { parent.leftChild = newNode; } else { parent.rightChild = newNode; } //child指针父节点parent newNode.parent = parent; return newNode; } /** * 前序遍历 * @param root */ public void preOrderTraverse(TreeNode root) { if (root == null) return; System.out.println("pro Order : " + root.data); preOrderTraverse(root.leftChild); preOrderTraverse(root.rightChild); } /** * 中序遍历 时间复杂度 :O(n) * @param root */ public void midOrderTraverse(TreeNode root) { if (root == null) return; midOrderTraverse(root.leftChild); System.out.print(root.data + " "); midOrderTraverse(root.rightChild); } /** * * @param data * @return */ public TreeNode searchNode(int data) { if (root == null) return null; //比较right和left节点的大小 TreeNode node = root; //在java中不要使用 递归 while (node != null) { //比较当前节点 if (node.data == data) return node; else if (node.data < data) node = node.rightChild; else if (node.data > data) node = node.leftChild; } //不存节点在返回null return null; } /** * 删除一个节点 * @param node */ private void delNode(TreeNode node) { if (node == null) { //异常报错历 没有成 throw new NoSuchElementException(); } else { TreeNode parent = node.parent; //1,没有right 和left 子树 if ((node.leftChild == null) && (node.rightChild == null)) { //判断父节点是否为空 if (parent == null) { root = null; } else if (parent.leftChild == node) { parent.leftChild = null; } else if (parent.rightChild == node) { parent.rightChild = null; } node.parent = null; } else if ((node.leftChild != null) && (node.rightChild == null)) { //2,有left子树 if (parent == null) { node.parent = null; parent.leftChild.parent = null; //改变孩子的指针 root = node.leftChild; } else { if (parent.leftChild == node) { parent.leftChild = node.leftChild; } else if (parent.rightChild == node) { parent.rightChild = node.rightChild; } node.parent = null; } } else if ((node.leftChild == null) && (node.rightChild != null)) { //3,有ringht子树 if (parent == null) { node.parent = null; parent.rightChild.parent = null; //改变孩子的指针 root = node.rightChild; } else { if (parent.leftChild == node) { parent.leftChild = node.leftChild; } else if (parent.rightChild == node) { parent.rightChild = node.rightChild; } node.parent = null; } } else if ((node.leftChild != null) && (node.rightChild != null)) { //4,有letf, ringht树 if (node.rightChild.leftChild == null) { if (parent == null) { root = node.rightChild; } else { if (parent.leftChild == node) { parent.leftChild = node.rightChild; } else if (parent.rightChild == node) { parent.rightChild = node.rightChild; } } node.parent = null; } else { TreeNode newleftNode = MinleftNode(node.rightChild); //第一步 newleftNode.leftChild = node.leftChild; //第二步 TreeNode newleftNodeP = newleftNode.parent; newleftNodeP.leftChild = newleftNode.rightChild; //第三步 newleftNode.rightChild = node.rightChild; //第四步 if (parent == null) { root = newleftNode; } else { if (parent.leftChild == node) { parent.leftChild = newleftNode; } else if (parent.rightChild == node) { parent.rightChild = newleftNode; } } } //node.parent = null; //node = null; } } } /** * @param rightChild * @return */ private TreeNode MinleftNode(TreeNode node) { // TODO Auto-generated method stub if (node == null) { return null; } else { while (node.leftChild != null) { node = node.leftChild; } return node; } } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int arrays[] = {12, 3, 23, 5, 8, 1, 19, 2, 4, 56, 45, 34, 23, 33}; SearchBinaryTree tree = new SearchBinaryTree(); for (int i: arrays) tree.put(i); //打印 tree.midOrderTraverse(tree.root); //查找树 TreeNode node = tree.searchNode(23); //System.out.println(node != null ? node.data: null); System.out.println(); tree.delNode(node); //打印 tree.midOrderTraverse(tree.root); }}
阅读全文
0 0
- 二叉树(查询和删除)
- 二叉树·二叉搜索树·插入-查询-删除
- c++实现二叉树的插入、删除、查询、遍历和树形打印
- 二叉树(四)删除二叉树
- 平衡二叉树操作(查询树高、平衡因子、删除节点、插入节点)
- 二叉树,建立,查询,删除,插入的简单实现
- C++实现二叉树的插入、删除、查询、遍历
- 二叉查询树的保存和读取(Serialization/Deserialization)
- 二叉树操作(删除)
- 二叉搜索树的插入和删除
- 排序二叉树的插入和删除
- 二叉搜索树的插入和删除
- 二叉搜索树的插入和删除
- 二叉搜索树的插入和删除
- 二叉搜索树的插入和删除
- 二叉搜索树的插入和删除
- 二叉搜索树的删除和添加
- 二叉树的创建和遍历、删除
- 深入浅出REST
- 天气晴朗的魔法
- ubuntu c++ 关机 重启 挂起 API
- 默慈金数学习小记 && 51nod 1556 计算
- IT领域的奇葩解读——反摩尔定律
- 二叉树(查询和删除)
- Android开发日常快捷键(不断更新)
- git&github常用日常
- layui实现数据分页功能
- MySql 数据库“索引”初体验
- Secret Poems 2017ACM-ICPC北京赛区/hihoCoder1632
- RXDownload实现下载apk
- 分类中的训练数据集不均衡问题处理
- Anaconda+python 进行FFT算法