/*************************************************************************

这是一个二叉查找树,实现了以下操作:插入结点、构造二叉树、删除结点、查找、

查找最大值、查找最小值、查找指定结点的前驱和后继。上述所有操作时间复杂度

均为o(h),其中h是树的高度

注释很详细,具体内容就看代码吧

*************************************************************************/

#include<stdio.h>

#include<stdlib.h>

//二叉查找树结点描述

typedef int KeyType;

typedef struct Node

{

KeyType key;          //关键字

struct Node * left;   //左孩子指针

struct Node * right;  //右孩子指针

struct Node * parent; //指向父节点指针

}Node,*PNode;

//往二叉查找树中插入结点

//插入的话,可能要改变根结点的地址,所以传的是二级指针

void inseart(PNode * root,KeyType key)

{

//初始化插入结点

PNode p=(PNode)malloc(sizeof(Node));

p->key=key;

p->left=p->right=p->parent=NULL;

//空树时,直接作为根结点

if((*root)==NULL){

*root=p;

return;

}

//插入到当前结点(*root)的左孩子

if((*root)->left == NULL && (*root)->key > key){

p->parent=(*root);

(*root)->left=p;

return;

}

//插入到当前结点(*root)的右孩子

if((*root)->right == NULL && (*root)->key < key){

p->parent=(*root);

(*root)->right=p;

return;

}

if((*root)->key > key)

inseart(&(*root)->left,key);

else if((*root)->key < key)

inseart(&(*root)->right,key);

else

return;

}

//查找元素,找到返回关键字的结点指针,没找到返回NULL

PNode search(PNode root,KeyType key)

{

if(root == NULL)

return NULL;

if(key > root->key) //查找右子树

return search(root->right,key);

else if(key < root->key) //查找左子树

return search(root->left,key);

else

return root;

}

//查找最小关键字,空树时返回NULL

PNode searchMin(PNode root)

{

if(root == NULL)

return NULL;

if(root->left == NULL)

return root;

else  //一直往左孩子找,直到没有左孩子的结点

return searchMin(root->left);

}

//查找最大关键字,空树时返回NULL

PNode searchMax(PNode root)

{

if(root == NULL)

return NULL;

if(root->right == NULL)

return root;

else  //一直往右孩子找,直到没有右孩子的结点

return searchMax(root->right);

}

//查找某个结点的前驱

PNode searchPredecessor(PNode p)

{

//空树

if(p==NULL)

return p;

//有左子树、左子树中最大的那个

if(p->left)

return searchMax(p->left);

//无左子树,查找某个结点的右子树遍历完了

else{

if(p->parent == NULL)

return NULL;

//向上寻找前驱

while(p){

if(p->parent->right == p)

break;

p=p->parent;

}

return p->parent;

}

}

//查找某个结点的后继

PNode searchSuccessor(PNode p)

{

//空树

if(p==NULL)

return p;

//有右子树、右子树中最小的那个

if(p->right)

return searchMin(p->right);

//无右子树,查找某个结点的左子树遍历完了

else{

if(p->parent == NULL)

return NULL;

//向上寻找后继

while(p){

if(p->parent->left == p)

break;

p=p->parent;

}

return p->parent;

}

}

//根据关键字删除某个结点,删除成功返回1,否则返回0

//如果把根结点删掉,那么要改变根结点的地址,所以传二级指针

int deleteNode(PNode* root,KeyType key)

{

PNode q;

//查找到要删除的结点

PNode p=search(*root,key);

KeyType temp;    //暂存后继结点的值

//没查到此关键字

if(!p)

return 0;

//1.被删结点是叶子结点,直接删除

if(p->left == NULL && p->right == NULL){

//只有一个元素,删完之后变成一颗空树

if(p->parent == NULL){

free(p);

(*root)=NULL;

}else{

//删除的结点是父节点的左孩子

if(p->parent->left == p)

p->parent->left=NULL;

else  //删除的结点是父节点的右孩子

p->parent->right=NULL;

free(p);

}

}

//2.被删结点只有左子树

else if(p->left && !(p->right)){

p->left->parent=p->parent;

//如果删除是父结点,要改变父节点指针

if(p->parent == NULL)

*root=p->left;

//删除的结点是父节点的左孩子

else if(p->parent->left == p)

p->parent->left=p->left;

else //删除的结点是父节点的右孩子

p->parent->right=p->left;

free(p);

}

//3.被删结点只有右孩子

else if(p->right && !(p->left)){

p->right->parent=p->parent;

//如果删除是父结点,要改变父节点指针

if(p->parent == NULL)

*root=p->right;

//删除的结点是父节点的左孩子

else if(p->parent->left == p)

p->parent->left=p->right;

else //删除的结点是父节点的右孩子

p->parent->right=p->right;

free(p);

}

//4.被删除的结点既有左孩子,又有右孩子

//该结点的后继结点肯定无左子树(参考上面查找后继结点函数)

//删掉后继结点,后继结点的值代替该结点

else{

//找到要删除结点的后继

q=searchSuccessor(p);

temp=q->key;

//删除后继结点

deleteNode(root,q->key);

p->key=temp;

}

return 1;

}

//创建一棵二叉查找树

void create(PNode* root,KeyType *keyArray,int length)

{

int i;

//逐个结点插入二叉树中

for(i=0;i<length;i++)

inseart(root,keyArray[i]);

}

int main(void)

{

int i;

PNode root=NULL;

KeyType nodeArray[11]={15,6,18,3,7,17,20,2,4,13,9};

create(&root,nodeArray,11);

for(i=0;i<2;i++)

deleteNode(&root,nodeArray[i]);

printf("%d\n",searchPredecessor(root)->key);

printf("%d\n",searchSuccessor(root)->key);

printf("%d\n",searchMin(root)->key);

printf("%d\n",searchMax(root)->key);

printf("%d\n",search(root,13)->key);

return 0;

}

C++实现二叉树(转)的更多相关文章

  1. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  2. 二叉树的递归实现(java)

    这里演示的二叉树为3层. 递归实现,先构造出一个root节点,先判断左子节点是否为空,为空则构造左子节点,否则进入下一步判断右子节点是否为空,为空则构造右子节点. 利用层数控制迭代次数. 依次递归第二 ...

  3. c 二叉树的使用

    简单的通过一个寻找嫌疑人的小程序 来演示二叉树的使用 #include <stdio.h> #include <stdlib.h> #include <string.h& ...

  4. Java 二叉树遍历右视图-LeetCode199

    题目如下: 题目给出的例子不太好,容易让人误解成不断顺着右节点访问就好了,但是题目意思并不是这样. 换成通俗的意思:按层遍历二叉树,输出每层的最右端结点. 这就明白时一道二叉树层序遍历的问题,用一个队 ...

  5. 数据结构:二叉树 基于list实现(python版)

    基于python的list实现二叉树 #!/usr/bin/env python # -*- coding:utf-8 -*- class BinTreeValueError(ValueError): ...

  6. [LeetCode] Path Sum III 二叉树的路径和之三

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

  7. [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点

    Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...

  8. [LeetCode] Verify Preorder Serialization of a Binary Tree 验证二叉树的先序序列化

    One way to serialize a binary tree is to use pre-oder traversal. When we encounter a non-null node, ...

  9. [LeetCode] Binary Tree Vertical Order Traversal 二叉树的竖直遍历

    Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bott ...

  10. [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列

    Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...

随机推荐

  1. 编译u-boot命令和u-boot常用命令

    一.编译u-boot命令 1.配置开发板 #make TQ2440_config 2.编译 #make all 3.交叉编译器是crosstools_3.4.5_softfloat” 使用4.3.3版 ...

  2. CentOS 6.0 图文安装教程

    CentOS 6.0下载地址:wget http://ftp.riken.jp/Linux/centos/6.0/isos/i386/CentOS-6.0-i386-bin-DVD.iso 下边就是安 ...

  3. [BZOJ 3282] Tree 【LCT】

    题目链接:BZOJ - 3282 题目分析 这道题是裸的LCT,包含 Link , Cut 和询问两点之间的路径信息. 写代码时出现的错误:Access(x) 的循环中应该切断的是原来的 Son[x] ...

  4. 【NOIP 2011】 观光公交

    题目描述 Description 风景迷人的小城 Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0 分钟出现在1号 ...

  5. uva 10496 Collecting Beepers

    一个简单的货郎担问题,用状态压缩dp可以解决: 解法: d(i,S)=min{d(j,S-{j})+dis(i,j) | j belongs to S}; 边界条件:d(i,{})=dis(0,i). ...

  6. JPA2.1 中三个提升应用性能的新功能

    经常在网上看到开发者们抱怨 JPA 性能低下的帖子或文章,但如果仔细查看这些性能问题,常会发现导致问题的根本原因大致包括以下几个: 使用过多的 SQL 查询从数据库中获取所需的实体信息,即我们常说的n ...

  7. Katu Puzzle

    poj3678:http://poj.org/problem?id=3678 题意:给你一些数,然后这些要么是0要么是1,然后回给出一些数之间的and,or,xor的值,问你是否存在一组解. 题解:2 ...

  8. Delphi常用排序

    1.冒泡排序 Delphi/Pascal code   ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 procedure BubbleSort(var x:a ...

  9. Android开源项目发现--- 工具类图片缓存篇(持续更新)

    1. Android-Universal-Image-Loader 图片缓存 目前使用最广泛的图片缓存,支持主流图片缓存的绝大多数特性. 项目地址:https://github.com/nostra1 ...

  10. 内存管理(memory allocation内存分配)

    Memory management is the act of managing computer memory. The essential requirement of memory manage ...