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

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

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

均为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. linux制作文件系统

    1.获取文件系统源码并解压 这里使用的源码是天嵌提供的“root_qtopia_2.2.0_2.6.30.4_20100601.tar.bz2” #tar xvf root_qtopia_2..0_2 ...

  2. 大话设计模式之策略模式(strategy)

    策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响使用算法的用户. 针对商城收银模式,打折,返现促销等的例子: 打折还是促销其实都是一些算法,可以用工厂模式来 ...

  3. Apriori算法在购物篮分析中的运用

    购物篮分析是一个很经典的数据挖掘案例,运用到了Apriori算法.下面从网上下载的一超市某月份的数据库,利用Apriori算法进行管理分析.例子使用Python+MongoDB 处理过程1 数据建模( ...

  4. TCP连接建立和关闭中的疑难点

    TCP连接建立和关闭中的疑难点 作者:夏语岚    撰写日期:2011-10-29 近日在阅读<Unix网络编程>,以前在<计算机网络>课程中学到TCP,当时只是简单了解了TC ...

  5. PHP 7 探针的安装与测试

    首先,这是一篇软文,没错!就是一篇软文.因为我知道「PHP 是世界上最好的语言」,所以我相信很多人愿意读这篇用户帮忙写的软文,因为这篇软文应该能帮助 PHP 开发的同学一点小忙.我们是一家成立了7年的 ...

  6. MYSQL简单安装配置

    有用的URL: http://www.cnblogs.com/zeroone/articles/2298942.html http://blog.csdn.net/h1017597898/articl ...

  7. [jobdu]调整数组顺序使奇数位于偶数前面

    这道题的代码没啥好说的,用了O(n)的空间就是水题了.但可以讲一下思考过程.一开始是想O(1)的空间的,然后想从左往右双指针扫,然后根据出现顺序交换遇到的偶数和奇数.但遇到一个问题:1, 2, 3, ...

  8. QT变异版本下载(SJLJ长跳转,DWARF不传递错误(32位专用),SEH(64位专用)),以及QT的实验室项目

    http://www.tver-soft.org/ http://sourceforge.net/projects/qt64ng/ ---------------------------------- ...

  9. poj -2975 Nim

      Nim Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4312   Accepted: 1998 Description ...

  10. NGU-学习笔记(1)-动态添加删除图集

    现在 正在做unity的方向 不得不说我选的是UI方向 Unity中很有名的就是NGUI插件了.今天做了个ngui的简单背包系统.非常简陋..初学着 自己mark下 (1)预览 主要就是个 simpl ...