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

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

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

均为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. Ubuntu启动错误Checking Battery State的处理

    一.问题描述 二.处理方法 方法一: 按下 ctrl + alt + F1,进入终端,使用管理员权限执行下列代码 sudo rm /etc/X11/xorg.conf sudo reboot 方法二: ...

  2. [原创]dm642_HPI调通并boot成功

    一直在折腾前段时间画好的dm642+lpc4357板子,说明下这个板子的结构: 主芯片为DM642,这个片子很老了,但因为对这个片子熟悉,别折腾 没有给DM642加FLASH,配了一片LPC4357, ...

  3. Spring4.0整合Hibernate3 .6

    转载自:http://greatwqs.iteye.com/blog/1044271 6.5  Spring整合Hibernate 时至今日,可能极少有J2EE应用会直接以JDBC方式进行持久层访问. ...

  4. c语言技巧--长期更新

    1.   #define LOWER(c)            (unsigned char)(c | 0x20) 换成小写 2.   gcc -Wall -Werror //告警当成 错误来处理 ...

  5. 听同事讲 Bayesian statistics: Part 1 - Bayesian vs. Frequentist

    听同事讲 Bayesian statistics: Part 1 - Bayesian vs. Frequentist   摘要:某一天与同事下班一同做地铁,刚到地铁站,同事遇到一熟人正从地铁站出来. ...

  6. ExecutorService介绍2

    Thread和ExecutorService的区别 使用Thread,当子线程执行结束后,主线程如果没有其他执行任务,主线程会终止. /** * Created by litao on 15/10/7 ...

  7. NOT EXISTS优化

    INSERT INTO F_PTY_INDIV (PTY_ID, PTY_NAME, GENDER_CD, BIRTHDAY, CERT_TYPE, CERT_NO, SOCINSUR_NO, COU ...

  8. ECHO.js 纯javascript轻量级延迟加载

    演示 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf ...

  9. bzoj3083 3306

    又见bzoj的语言歧视,囧……bzoj3083过了本地的数据在上面出现各种奇葩的TLE835083 phile 3083 Time_Limit_Exceed 17092 kb 4872 ms Pasc ...

  10. Delphi socket() 函数的应用

    socket()系统调用,带有三个参数: 1.参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4), PF_INET6(IPv6)等 2.type指明通信类型,最常用 ...