C语言实现二叉排序树的增删查操作

来源:互联网 发布:域名购买哪家网站靠谱 编辑:程序博客网 时间:2024/06/05 07:12
#include <stdio.h>#include <stdlib.h>typedef struct TreeNode{    struct TreeNode* lchild;    struct TreeNode* rchild;    int val;}TreeNode;//构造树节点TreeNode* createTreeNode(int val){    TreeNode *node;    node = (TreeNode*)malloc(sizeof(TreeNode));    node->val = val;    node->lchild = NULL;    node->rchild = NULL;    return node;}//创建树TreeNode* createTree(int *array,int length){  TreeNode *root = createTreeNode(array[0]);  TreeNode *temp = root;  TreeNode *parent = root;  int i = 1;  while(i<length){        temp = root;    while(temp){            parent = temp;        if(temp->val>array[i]){            temp = temp->lchild;        }        else if(temp->val<array[i]){             temp = temp->rchild;        }        else{            break;        }    }    if(parent->val>array[i])        parent->lchild=createTreeNode(array[i]);    else        parent->rchild=createTreeNode(array[i]);    i++;  }  return root;}//递归寻找删除节点的位置void del(TreeNode *node,int key,TreeNode *parent){    if(node==NULL)        return;    if(key==node->val){        deleteNode(node,parent);    }    else if(key>node->val){        del(node->rchild,key,node);    }else{        del(node->lchild,key,node);    }}//删除节点的核心方法void deleteNode(TreeNode *node,TreeNode *parent){    int flag = -1;    if(parent->lchild==node){            flag=1;    }else{            flag=0;    }    if(node->lchild==NULL&&node->rchild==NULL){        if(flag==1){            parent->lchild = NULL;        }else{            parent->rchild = NULL;        }    }    else if(node->lchild!=NULL&&node->rchild==NULL){//删除节点有左子树            //重接左子树            if(flag==1){                parent->lchild = node->lchild;            }else{                 parent->rchild = node->lchild;            }    }    else if(node->rchild!=NULL&&node->lchild==NULL){//删除节点有右子树            //重接右子树            if(flag==1){                parent->lchild = node->rchild;            }else{                 parent->rchild = node->rchild;            }    }else{        //左右子树都不空        //右子树取最小的拿过来替代删除节点 或者将删除节点左子树上最大的替代 因为左子树最大的和右子树最小的都一定是叶子节点        //替代之后,既能保持排序二叉树的特性,移除叶子节点也很轻松        TreeNode *pre = node;        TreeNode *in = node->rchild;//往右一步        while(in->lchild){//向左搜索 找到最左边的            pre = in;//保存前缀节点            in = in->lchild;        }        //替补        node->val = in->val;        if(pre==node)//判断删除节点右子树是否只有一个节点            pre->rchild = NULL;        else//如果不是 则删除pre的左子树            pre->lchild = NULL;    }}//先序输出void output(TreeNode *root){    if(root==NULL)        return;    printf("%d  ",root->val);    output(root->lchild);    output(root->rchild);}//查找节点TreeNode* searchTree(TreeNode *root,int key){    if(root==NULL){        return NULL;    }    if(root->val==key){        return root;    }    root->val>key?searchTree(root->lchild,key):searchTree(root->rchild,key);//向左或向右查找}//插入节点TreeNode* insertNode(int value,TreeNode *root){    if(root==NULL){        TreeNode *node = createTreeNode(value);        return node;    }    if(root->val == value){//如果相等 则直接返回        return root;    }    if(root->val>value){        //向左遍历        root->lchild = insertNode(value,root->lchild);    }else{//向右遍历        root->rchild = insertNode(value,root->rchild);    }    return root;}int main(){    int a[7]={10,5,17,20,6,15,18};    TreeNode *root = createTree(a,7);    root = insertNode(17,root);//插入    output(root);    del(root,10,root);//删除    output(root);    //查找    TreeNode *node = searchTree(root,20);    output(node);    return 0;}

0 0