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

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

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

均为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. 网页端启动WinForm

    网页端启动WinForm 程序 在逛淘宝或者使用QQ相关的产品的时候,比如淘宝我要联系店家点击旺旺图标的时候能够自动启动阿里旺旺进行聊天.之前很奇怪为什么网页端能够自动启动客户端程序,最近在开发吉特仓 ...

  2. 百度云推送 pem

    1. p12证书导出 在钥匙串访问中选中推送证书,导出为个人信息交换文件(.p12格式). 选择文件格式.文件名和保存路径. 输入导出密码. 2. pem证书生成 将p12证书文件转换成pem证书文件 ...

  3. System.Reflection.Assembly.GetEntryAssembly()获取的为当前已加载的程序集

    今天在使用System.Reflection.Assembly.GetEntryAssembly()获取程序集时,发现获取的程序集不全.原来是因为C#的程序集为延迟加载,此方法只获取当前已加载的,未加 ...

  4. Linq 数据合并,比较,连接,交叉 维恩图工具

    Except 返回包含两个不同之处的linq结果集 Intersect 返回两个容器中共同的数据项 Union 返回所有成员,相同的成员出现多次,将只返回一个 Concat 返回所有数据项

  5. Linux 继续进阶

    http://www.cnblogs.com/uhasms/archive/2011/11/15/2250474.html http://www.cnblogs.com/alexyuyu/articl ...

  6. [BZOJ 1029] [JSOI2007] 建筑抢修 【贪心】

    题目链接:BZOJ - 1029 题目分析 使用一种贪心策略. 现将任务按照deadline从小到大排序. 然后枚举每一个任务,如果当前消耗的时间加上完成这个任务的时间不会超过这个任务的deadlin ...

  7. iOS获取键盘的高度

  8. win7+ubuntu双系统安装方法

    转自win7+ubuntu双系统安装方法 前段时间又安装一下win7+ubuntu双系统,过段时间就会忘记,这次自己写下来,以便以后查看. 1.      先准备一个分区来安装ubuntu.在win7 ...

  9. Unity3D 命令行参数

    Unity3D 命令行参数 @by 广州小龙                                              unity ios开发群:63438968 Typically, ...

  10. 如何用 React Native 创建一个iOS APP?(三)

    前两部分,<如何用 React Native 创建一个iOS APP?>,<如何用 React Native 创建一个iOS APP (二)?>中,我们分别讲了用 React ...