c语言实现二叉查找树实例方法

以下为算法详细流程及其实现。由于算法都用伪代码给出,就免了一些文字描述。

代码如下:

/*******************************************
=================JJ日记=====================
作者: JJDiaries(阿呆)
邮箱:JJDiaries@gmail.com
日期: 2013-11-13
============================================
二叉查找树,支持的操作包括:SERACH、MINIMUM、
MAXIMUM、PREDECESSOR、SUCCESSOR、INSERT、DELETE。
定理:对于一个高度为h的二叉查找树,操作SERACH、MINIMUM、
MAXIMUM、PREDECESSOR、SUCCESSOR的运行时间均为O(h)
*******************************************/

/*================JJ日记=====================
作者: JJDiaries(阿呆)
邮箱:JJDiaries@gmail.com
日期: 2013-11-13
============================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORDLEN 16
//定义一个节点,除了存放key值外,还包含了一个data字符数组用于存放一个单词
struct node{
    int key;
    char data[WORDLEN];
    struct node *parent;
    struct node *left;
    struct node *right;
};
typedef struct node * tree;

/*============================================
树的中序遍历
INORDER_TREE_WALK(x)
    if x!=NIL
        then INORDER_TREE_WALK(left[x])
             print key[x]
             INORDER_TREE_WALK(left[x])
============================================*/   
void inorder_tree_walk(tree T)
{
    if(T!=NULL){
        inorder_tree_walk(T->left);
        printf("key:%d   words:%s\n",T->key,T->data);
        inorder_tree_walk(T->right);
    }
}

/*============================================
树的搜索,返回含有关键字k的结点
TREE_SEARCH(x,k) //递归版本
    if x=NIL or k =key[x]
        then return x
    if k<key[x]
        then return TREE_SEARCH(left[x],k)
        else return TREE_SEARCH(right[x],k)

TREE_SEARCH(x,k) //非递归版本
    while x!=NIL and k!= key[x]
        do if k<key[x]
            then x <—— left[x]
            else x <—— right[x]
    return x
============================================*/
//递归版本
struct node* tree_search(tree T,int k)
{
    if(T==NULL || k == T->key)
        return T;
    if(k < T->key)
        return tree_search(T->left,k);
    else
        return tree_search(T->right,k);
}
//非递归版本
struct node* tree_search1(tree T,int k)
{
    while(T!=NULL && T->key!=k)
        if(k < T->key)
            T=T->left;
        else
            T=T->right;
    return T;
}

/*============================================
返回key值最小的结点
TREE_MINIMUM(x)
    while left[x]!=NIL
        do x <—— left[x]
    return x
============================================*/   
struct node* tree_minimum(tree T)
{
    while(T->left != NULL)
        T=T->left;
    return T;
}

/*============================================
返回key值最大的结点
TREE_MAXMUM(x)
    while right[x]!=NIL
        do x <—— right[x]
    return x
============================================*/
struct node* tree_maxmum(tree T)
{
    while(T->right != NULL)
        T=T->right;
    return T;
}
/*============================================   
中序遍历下,返回某一结点的后继结点
1)如果结点x有右子结点,则其后继结点为右子树中最小结点。
2)如果结点x没有右子树,且x有一个后继y,则y是x的最低祖先结点
且y的左儿子也是x的祖先。
TREE_SUCCESSOR(x)
    if right[x] != NIL
        return TREE_MINIMUM(right[x])
    y=p[x]
    while y!=NIL and x=right[y] //如果x=left[y],那么x的后继就是y,跳出while循环,直接返回y即可
        do x <—— y
           y <—— p[y]
    return y
============================================*/   
struct node * tree_successor(struct node *T)
{
    if(T->right!=NULL)
        return tree_minimum(T->right);
    struct node *y=T->parent;
    while(y!=NULL && T == y->right){
        T=y;
        y=y->parent;
    }
    return y;
}

/*===========================================
插入操作
思路:从根节点一路往下寻找插入位置,用指针x跟踪这条寻找路径,并用指针y指向x的父结点
TREE_INSERT(T,z)
    y=NIL
    x=root[T]
    while x!= NIL //直到x为空,这个空位置即为需要插入的位置
        do y<—— x
            if key[z]<key[x]
                then x <—— left[x]
                else x <—— right[x]
    p[z]=y
    if y=NIL
        then root[T]=z //树T为空时的情况
        else if key[z] < key[y]
            then left[y]=z //小于y的插在左边,大于的插在右边
            else right[y]=z
============================================*/   
void tree_insert(tree *PT,struct node *z)
{
    if(*PT==NULL){//树为空,则将z作为根结点返回
        *PT=z;
        return;
    }
    struct node *y=NULL;
    struct node *x=*PT;
    while(x!=NULL){
        y=x;
        if(z->key < x->key)
            x=x->left;
        else
            x=x->right;
    }
    z->parent=y;
    if(z->key < y->key)
        y->left=z;
    else
        y->right=z;
}

/*===============================================
删除操作
删除操作分为三类情况:
1)若要删除的节点z没有子女,则只需修改z的父节点的该子女为NIL即可
2)若要删除的节点z只有一个子女,则只需将z的这个子女与z的父节点连接起来即可
3)若要删除的节点z有两个子女,则需要先删除z的后继y,再用y的内容替换z的内容。
TREE_DELETE(T,z)
    if left[z]=NIL || right[z]=NIL  //把要删除的节点先保存在y中
        then y <—— z 
        else y <—— TREE_SUCCESSOR(z)
    if left[y]!=NIL                 //将y的非空子女存放在x中
        then X <—— left[y]
        else x <—— right[y]
    if x!=NIL
        then p[x]=p[y]    //将要删除节点的子女连接到要删除节点的父节点上
    if p[y]=NIL     //如果要删除的节点为根节点
        then root[T] <—— x
        else if y=left[p[y]]//
            then left[p[y]] <—— x
            else right[p[y]] <—— x
    if y!=z  //第三种情况,需要用y的内容替换z的内容
        then key[z] <—— key[y]
            copy y's other data to z
    return y
==============================================*/
struct node * tree_delete(tree *PT,struct node *z)
{
    struct node *delnode,*sonnode;
    if(z->left==NULL || z->right == NULL)//有一个子女或无子女,则要删除的结点结尾z本身
        delnode=z;
    else                                 //有两个子女,则要删除的结点为z的后继结点
        delnode=tree_successor(z);

if(delnode->left!=NULL)
        sonnode=delnode->left;
    else
        sonnode=delnode->right;

if(sonnode!=NULL)
        sonnode->parent=delnode->parent;
    if(delnode->parent==NULL)
        *PT=sonnode;
    else if(delnode->parent->left==delnode)
        delnode->parent->left=sonnode;
    else
        delnode->parent->right=sonnode;
    if(delnode!=z){
        z->key=delnode->key;
        strcpy(z->data,delnode->data);
    }
    return delnode;
}
//初始化一棵树
tree init_tree(int key)
{   
    struct node * t;
    t=(tree)malloc(sizeof(struct node));
    if(t==NULL)
        return NULL;
    t->key=key;
    t->parent=t->left=t->right=NULL;
    return t;
}
//释放资源
void fini_tree(tree T)
{
    if(T!=NULL){
        fini_tree(T->left);
        fini_tree(T->right);
        printf("free node(%d,%s) now\n",T->key,T->data);
        free(T);

}
}
//测试程序
int main()
{
    tree myTree=init_tree(256);
    if(myTree==NULL)
        return 1;
    strcpy(myTree->data,"JJDiaries");
    struct record{
    int key;
    char word[WORDLEN];
    };
    struct record records[]={ {2,"Viidiot"},
                     {4,"linux-code"},
                     {123,"google"},
                     {345,"baidu"},
                     {543,"nsfocus"}
                    };
    int i;
    struct node *tmp;
    for(i=0;i<5;++i){
        tmp=(tree)malloc(sizeof(struct node));
        if(tmp==NULL)
            continue;
        tmp->key=records[i].key;
        strcpy(tmp->data,records[i].word);
        tmp->left=tmp->right=tmp->parent=NULL;
        tree_insert(&myTree,tmp);
    }
    inorder_tree_walk(myTree);
    struct node *del;
    del=tree_delete(&myTree,tree_search(myTree,345));
    printf("Delete node(%d,%s)\n",del->key,del->data);
    free(del);
    inorder_tree_walk(myTree);
    fini_tree(myTree);
}

程序运行结果:
jjdiaries@ubuntu>./search_tree
key:2 words:Viidiot
key:4 words:linux-code
key:123 words:google
key:256 words:JJDiaries
key:345 words:baidu
key:543 words:nsfocus
Delete node(345,baidu)
key:2 words:Viidiot
key:4 words:linux-code
key:123 words:google
key:256 words:JJDiaries
key:543 words:nsfocus
free node(123,google) now
free node(4,linux-code) now
free node(2,Viidiot) now
free node(543,nsfocus) now
free node(256,JJDiaries) now

(0)

相关推荐

  • C语言实现二叉树遍历的迭代算法

    本文实例讲述了C语言实现二叉树遍历的迭代算法,是数据结构算法中非常经典的一类算法.分享给大家供大家参考. 具体实现方法如下: 二叉树中序遍历的迭代算法: #include <iostream> #include <stack> using namespace std; struct Node { Node(int i, Node* l = NULL, Node* r = NULL) : item(i), left(l), right(r) {} int item; Node* le

  • C语言实现计算树的深度的方法

    本文实例讲述了C语言实现计算树的深度的方法.是算法设计中常用的技巧.分享给大家供大家参考.具体方法如下: /* * Copyright (c) 2011 alexingcool. All Rights Reserved. */ #include <iostream> using namespace std; struct Node { Node(int i = 0, Node *l = NULL, Node *r = NULL) : data(i), left(l), right(r) {}

  • 一波C语言二元查找树算法题目解答实例汇总

    按层次遍历二元树 问题描述:输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印.  例如输入: 8 / / 6 10 / / / / 5 7 9 11 输出 8 6 10 5 7 9 11 定义二元树(其实是二元搜索树,但并不遍历算法)的结点为: struct BSTreeNode { int value; BSTreeNode *left; BSTreeNode *right; }; 思路:利用队列的先进先出,很容易实现.每次取出队列的首元素,然后将其左右子女放入队列

  • c语言版本二叉树基本操作示例(先序 递归 非递归)

    复制代码 代码如下: 请按先序遍历输入二叉树元素(每个结点一个字符,空结点为'='):ABD==E==CF==G== 先序递归遍历:A B D E C F G中序递归遍历:D B E A F C G后序递归遍历:D E B F G C A层序递归遍历:ABCDEFG先序非递归遍历:A B D E C F G中序非递归遍历:D B E A F C G后序非递归遍历:D E B F G C A深度:请按任意键继续. . . 复制代码 代码如下: #include<stdio.h>#include&

  • C语言实现找出二叉树中某个值的所有路径的方法

    本文实例讲述了C语言实现找出二叉树中某个值的所有路径的方法,是非常常用的一个实用算法技巧.分享给大家供大家参考. 具体实现方法如下: #include <iostream> #include <vector> #include <iterator> #include <algorithm> using namespace std; vector<int> result; struct Node { Node(int i = 0, Node *pl

  • 使用C语言求二叉树结点的最低公共祖先的方法

    算法分析 我们直接来分析O(n)的算法. 比如求节点F和节点H的最低公共祖先,先求出从根节点A到F的路径,再求出A到H的路径,那么最后一个相同的节点就是最低公共祖先.A->B->D->F和A->B->E->H,最后相同的节点事B,所以最低公共祖先是B节点.求根节点到指定节点的算法先前已经更新过了,复杂度是O(n),所以总的时间复杂度是O(n). 条件细化: (1)树如果是二叉树,而且是二叉排序树.              这中条件下可以使用二叉排序树的搜索功能找到最低

  • C语言二叉树的非递归遍历实例分析

    本文以实例形式讲述了C语言实现二叉树的非递归遍历方法.是数据结构与算法设计中常用的技巧.分享给大家供大家参考.具体方法如下: 先序遍历: void preOrder(Node *p) //非递归 { if(!p) return; stack<Node*> s; Node *t; s.push(p); while(!s.empty()) { t=s.top(); printf("%d\n",t->data); s.pop(); if(t->right) s.pus

  • 使用C语言构建基本的二叉树数据结构

    二叉树结构常用的一些初始化代码 #include #include typedef struct Node{ int data; Node *leftchild; Node *rightchild; }Node; /* 初始化一棵二叉树排序树. */ void InitBinaryTree(Node**root,int elem) { *root=(Node*)malloc(sizeof(Node)); if(!(*root)) { printf("Memory allocation for r

  • C语言实现输入一颗二元查找树并将该树转换为它的镜像

    本文实例讲述了C语言实现输入一颗二元查找树并将该树转换为它的镜像的方法,分享给大家供大家参考.具体实现方法如下: 采用递归方法实现代码如下: /* * Copyright (c) 2011 alexingcool. All Rights Reserved. */ #include <iostream> #include <iterator> #include <algorithm> using namespace std; struct Node { Node(int

  • 用C语言判断一个二叉树是否为另一个的子结构

    1.问题描述: 如何判断一个二叉树是否是另一个的子结构?      比如: 2       /   \      9    8     / \    /    2  3  5   / 6 有个子结构是    9   / \ 2  3 2.分析问题:     有关二叉树的算法问题,一般都可以通过递归来解决.那么写成一个正确的递归程序,首先一定要分析正确递归结束的条件. 拿这道题来讲,什么时候递归结束. <1>第二个二叉树root2为空时,说明root2是第一棵二叉树的root1的子结构,返回tr

随机推荐