二叉搜索树

本文展示了如何使用C语言实现二叉搜索树,包括建立、遍历、搜索、查找最大值和最小值、获取前置节点和后置节点、插入及删除节点等操作。代码实现包括先序、中序和后序遍历,以及对数组进行排序和快速排序的辅助函数。
摘要由CSDN通过智能技术生成

二叉搜索树的实现

二叉搜索树

使用C语言实现了二叉搜索树,直接贴代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define arrsort arrisort
#define NULL ((void *)0)
//定义树节点
struct TreeNode {
    struct TreeNode* pnode;//父节点
    struct TreeNode* lnode;//左孩子节点
    struct TreeNode* rnode;//右孩子节点
    int val;//节点值
};
typedef struct TreeNode Tree;
//树节点占用存储
const int TREE_NODE_SIZE=sizeof(struct TreeNode);
const int INT_SIZE = sizeof(int);
const null = 0;

//声明函数调用
void arrprintf(const int[], int);//数组打印
void arrsort(int arr[], int l, int r);//数组排序
Tree* treeBuild(int val[], int l, int r);//二叉树建立
void treeFree(struct TreeNode* proot);//二叉树资源释放
void treeWalkPre(struct TreeNode* proot,int rflag);//先序遍历
void treeWalkPos(struct TreeNode* proot, int rflag);//后续遍历
void treeWalkIno(struct TreeNode* proot, int rflag);//中序遍历
struct TreeNode* treeSearch(struct TreeNode* p, int key);//二叉树搜索
struct TreeNode* treeMax(struct TreeNode* p);//最大直
struct TreeNode* treeMin(struct TreeNode* p);//最小值
struct TreeNode* treePreNode(struct TreeNode* pnode);//前置节点
struct TreeNode* treeNextNode(struct TreeNode* pnode);//后置节点
void treeInsert(struct TreeNode* proot, struct TreeNode* pnew);//节点新增
struct TreeNode* nodeBuild();//创立node
Tree* treeDelete(struct TreeNode* proot, struct TreeNode* pdelete);

int main(){
    const int arr[] = { 52,23,43,75,0,37,58,76,79,19,31,14,47,92,74,80,32,62,81,51,68,69,26,27,1,16,25,84,78,28,66,59,100,44,15,50,90,73,87,21,39,97,61,63,40,82,30,10,34,12,95,45,56,71,48,91,33,53,46,29,24,4,67,8,99,85,41,55,88,5,2,42,98,11,7,94,60,9,86,38,13,35,3,20,83,70,57,72,54,89,49,64,77,96,22,65,17,18,93,6 };
    //const int arr[] = { 46,59,16,77,36,49,54,38,6,44,21,63,4,62,99,76};
    const arrlen = sizeof(arr) / sizeof(int);//获取数组大小
    int* parr =NULL;
    struct TreeNode* proot;
    struct TreeNode* ptmp;
    struct TreeNode* ptmp2;
    parr = (int*)malloc(INT_SIZE* arrlen);
    int i;
    if (parr == NULL) {
        return 1;
    }
    memcpy(parr, arr, INT_SIZE * arrlen);
    arrsort(parr,0, arrlen -1);
    arrprintf(arr, arrlen);
    arrprintf(parr, arrlen);
    proot= treeBuild(parr,0,arrlen-1);
    //二叉树遍历
    treeWalkIno(proot,1);
    treeWalkPre(proot,1);
    treeWalkPos(proot, 1);
    //二叉树搜索
    ptmp=treeSearch(proot, 100);
    if (!ptmp) {
        printf("treeSearch,100:ptmp == null\n");
    }
    else {
        printf("treeSearch,100:%d\n",ptmp->val);
    }
    ptmp = treeSearch(proot, 77);
    if (!ptmp) {
        printf("treeSearch,77:ptmp == null\n");

    }
    else {
        printf("treeSearch,77:%d\n", ptmp->val);
    }




    ptmp = treeSearch(proot, 68);
    if (!ptmp) {
        printf("treeSearch,68:ptmp == null\n");

    }
    else {
        printf("treeSearch,68:%d\n", ptmp->val);
    }

    //最大值
    ptmp = treeMax(proot);
    if (!ptmp) {
        printf("treeMax:ptmp == null\n");
    }
    else {
        printf("treeMax:%d\n", ptmp->val);
    }
    //最小值
    ptmp = treeMin(proot);
    if (!ptmp) {
        printf("treeMin:ptmp == null\n");
    }
    else {
        printf("treeMin:%d\n", ptmp->val);
    }

    //前置节点
    ptmp = treePreNode(treeSearch(proot, 99));
    if (ptmp != NULL) {
        printf("treePreNode(treeSearch(proot, 99)):%d\n", ptmp->val);
    }
    ptmp = treePreNode(treeSearch(proot, 2));
    if (ptmp != NULL) {
        printf("treePreNode(treeSearch(proot, 2)):%d\n", ptmp->val);
    }
    ptmp = treePreNode(treeSearch(proot, 77));
    if (ptmp != NULL) {
        printf("treePreNode(treeSearch(proot, 77)):%d\n", ptmp->val);
    }
    //后置节点
    ptmp = treeNextNode(treeSearch(proot, 99));
    if (ptmp != NULL) {
        printf("ttreeNextNode(treeSearch(proot, 99)):%d\n", ptmp->val);
    }
    ptmp = treeNextNode(treeSearch(proot, 2));
    if (ptmp != NULL) {
        printf("ttreeNextNode(treeSearch(proot, 2)):%d\n", ptmp->val);
    }
    ptmp = treeNextNode(treeSearch(proot, 77));
    if (ptmp != NULL) {
        printf("ttreeNextNode(treeSearch(proot, 77)):%d\n", ptmp->val);
    }
    //插入节点
    ptmp2=nodeBuild();
    if (ptmp2) {
        ptmp2->val = 100;
        treeInsert(proot, ptmp2);
    }
    //插入节点
    ptmp2 = nodeBuild();
    if (ptmp2) {
        ptmp2->val = 1;
        treeInsert(proot, ptmp2);
    }
    //中序遍历打印详情
    treeWalkIno(proot, 1);
    //
    ptmp = treeSearch(proot,100);
    proot=treeDelete(proot, ptmp);
    printf("treeDelete(proot,100):\n");
    treeWalkIno(proot, 1);
    printf("\n");
    ///

        //
    ptmp = treeSearch(proot, 1);
    proot = treeDelete(proot, ptmp);
    printf("treeDelete(proot,1):\n");
    treeWalkIno(proot, 1);
    printf("\n");
    ///
    for (i = 0; i < arrlen; i++) {
        ptmp = treeSearch(proot, arr[i]);
        proot = treeDelete(proot, ptmp);
        printf("treeDelete(proot,%d):\n",arr[i]);
        treeWalkIno(proot, 1);
        printf("\n");
    }
    //资源释放
    treeFree(proot);
    free(parr);
    return 0;
}
void arrswap(int* arr,int i,int j) {
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
//快速排序
void arrqsort(int arr[], int l, int r) {
    int key = arr[l];
    int li = l;
    int ri = r;
    if (l >= r) {
        return;
    }
    while (1) {
        //arrprintf(arr, 10);
        while (arr[ri] > key) {
            ri--;
        }
        while (arr[li] <= key && li < ri) {
            li++;
        }
        if (li == ri) {
            break;
        }
        arrswap(arr, li, ri);
    }
    arrswap(arr, l, li);
    arrsort(arr, l, li - 1);
    arrsort(arr, li + 1,r);
}
//插入排序
void arrisort(int arr[], int l, int r) {
    int i = 0, j = 0;
    int tmp = 0;
    for (i = l+1; i <= r; i++) {
        //arrprintf(arr, 10);
        tmp = arr[i];
        for (j = i - 1 ; j >= 0; j--) {
            if (arr[j]>tmp) {
                arr[j+1] = arr[j];
            }else {
                break;
            }
        }
        arr[j + 1] = tmp;

    }
}
void arrprintf(const int valarr[],int vallen) {

    int i;
    printf("arr:");
    for (i = 0; i < vallen; i++) {
        printf("%d ",valarr[i]);
    }
    printf("\n");
}
struct TreeNode* nodeBuild() {
    struct TreeNode* p = (struct TreeNode*)malloc(TREE_NODE_SIZE);
    if (p != NULL) {
        memset(p, 0, TREE_NODE_SIZE);
    }
    return p;
}
Tree* treeBuild(int val[],int l,int r) {
    int mid = (l + r) / 2;

    struct TreeNode* proot = NULL;
    if (l > r) {
        return NULL;
    }

    proot = nodeBuild();

    proot->lnode = treeBuild(val,l,mid-1);

    if (proot->lnode != NULL) {
        proot->lnode->pnode = proot;
    }
    proot->rnode = treeBuild(val, mid + 1, r);
    if (proot->rnode != NULL) {
        proot->rnode->pnode = proot;
    }
    proot->val = val[mid];
    return proot;
}
void treeFree(struct TreeNode* proot) {
    if (proot != NULL) {
        treeFree(proot->lnode);
        treeFree(proot->rnode);
        free(proot);
    }
}
//中序遍历
//打印出來的内容加上 <root>包裹可以查看层次结构
void treeWalkIno(struct TreeNode* proot,int rflag) {
    if (proot != NULL) {
        if (!!rflag) {
            printf("<treeWalkIno>");
        }
        if (proot->lnode != NULL) {
            printf("<lnode>");
            treeWalkIno(proot->lnode,0);
            printf("</lnode>");
        }
        printf("<val>%d</val>", proot->val);
        if (proot->rnode != NULL) {
            //printf("<test>x</test>");
            printf("<rnode>");
            treeWalkIno(proot->rnode,0);
            printf("</rnode>");
        }
        if (!!rflag) {
            printf("</treeWalkIno>");
        }

    }
}
//先序遍历
//打印出來的内容加上 <root>包裹可以查看层次结构
void treeWalkPre(struct TreeNode* proot,int rflag) {
  if (proot != NULL) {
        if (!!rflag) {
            printf("<treeWalkPre>");
        }
        printf("<val>%d</val>", proot->val);
        if (proot->lnode!=NULL) {
            printf("<lnode>");
            treeWalkPre(proot->lnode,0);
            printf("</lnode>");
        }
        if (proot->rnode != NULL) {
            //printf("<test>x</test>");
            printf("<rnode>");
            treeWalkPre(proot->rnode,0);
            printf("</rnode>");
        }
        if (!!rflag) {
            printf("</treeWalkPre>");
        }

    }
}
//后续遍历
//打印出來的内容加上 <root>包裹可以查看层次结构
void treeWalkPos(struct TreeNode* proot,int rflag) {
    if (proot != NULL) {
        if (!!rflag) {
            printf("<treeWalkPos>");
        }
        if (proot->lnode != NULL) {
            printf("<lnode>");
            treeWalkPos(proot->lnode,0);
            printf("</lnode>");
        }
        if (proot->rnode != NULL) {
            //printf("<test>x</test>");
            printf("<rnode>");
            treeWalkPos(proot->rnode,0);
            printf("</rnode>");
        }
        printf("<val>%d</val>", proot->val);
        if (!!rflag) {
            printf("</treeWalkPos>");
        }
    }
}
struct TreeNode* treeSearch(struct TreeNode* p,int key) {
    if (p == NULL) {
        return NULL;
    }
    if (p->val == key) {
        return p;
    }
    else if (p->val > key) {
        return treeSearch(p->lnode,key);
    }
    else {
        return treeSearch(p->rnode, key);
    }

}
struct TreeNode* treeMax(struct TreeNode* proot) {
    struct TreeNode* ptmp= proot;
    if (proot == NULL) {
        return NULL;
    }
    while (ptmp->rnode != NULL) {
        ptmp = ptmp->rnode;
    }
    return ptmp;

}
struct TreeNode* treeMin(struct TreeNode* p) {
    struct TreeNode* ptmp = p;
    if (p == NULL) {
        return NULL;
    }
    while (ptmp->lnode != NULL) {
        ptmp = ptmp->lnode;
    }
    return ptmp;

}
//前置节点
struct TreeNode* treePreNode(struct TreeNode* pnode) {
    struct TreeNode* ptmemp;
    if (pnode == NULL) {
        return NULL;
    }
    if (pnode->lnode) {
        return treeMax(pnode->lnode);
    }
    ptmemp = pnode;
    while (1) {
        if (ptmemp->pnode == NULL) {
            return NULL;
        }
        if (ptmemp->pnode->lnode == ptmemp) {
            ptmemp = ptmemp->pnode;
        }else if (ptmemp->pnode->rnode == ptmemp) {
            return ptmemp->pnode;
        }
    }
}
//后置节点
struct TreeNode* treeNextNode(struct TreeNode* pnode) {
    struct TreeNode* ptmemp;
    if (pnode == NULL) {
        return NULL;
    }
    if (pnode->rnode) {
        return treeMin(pnode->rnode);
    }
    ptmemp = pnode;
    while (1) {
        if (ptmemp->pnode == NULL) {
            return NULL;
        }
        if (ptmemp->pnode->rnode == ptmemp) {
            ptmemp = ptmemp->pnode;
        }
        else if (ptmemp->pnode->lnode == ptmemp) {
            return ptmemp->pnode;
        }
    }
}
void treeInsert(struct TreeNode* proot, struct TreeNode* pnew) {
    struct TreeNode* ptmp0;
    if (proot==NULL) {
        return ;
    }
    ptmp0 = proot;
    while (ptmp0 !=NULL) {
        if (pnew->val > ptmp0->val) {
            if (ptmp0->rnode == NULL) {
                //插到这里来
                ptmp0->rnode = pnew;
                pnew->pnode = ptmp0;
                return;
            }
            else {
                ptmp0 = ptmp0->rnode;
            }
        }
        else {
            if (ptmp0->lnode == NULL) {
                //插到这里来
                ptmp0->lnode = pnew;
                pnew->pnode = ptmp0;
                return;
            }
            else {
                ptmp0 = ptmp0->lnode;
            }

        }
    }
}
//如果删除的是根节点,直接返回新的根节点
//如果删除的不是根节点,返回proot
Tree* treeDelete(struct TreeNode* proot, struct TreeNode* pdelete) {


    //Tree* ptree;//子树
    //struct TreeNode* pback;//备份
    struct TreeNode* pfind;//用于替换的节点信息
    //struct TreeNode* ptmp;
   // struct TreeNode* pnew;
    struct TreeNode* prootNew=proot;
    //标志这个节点是父节点的左节点还是右节点0-左节点,1-右节点
    //int pcflag = 0;

    if (!pdelete) {
        return proot;
    }
    //如果右左节点
    if (pdelete->lnode) {


        pfind =treeMax(pdelete->lnode);

        //最大值为欲删除节点的左节点
        if (pfind == pdelete->lnode) {

            pfind->pnode = pdelete->pnode;//建立子父联系
            pfind->rnode = pdelete->rnode;//建立右子树的关系【这种情况是没有右子树的(pfind == pdelete->lnode)】
            if (pfind->pnode) {

                if (pdelete->pnode->lnode == pdelete) {
                    pdelete->pnode->lnode = pfind;//建立父子联系

                }else {
                    pdelete->pnode->rnode = pfind;//建立父子联系

                }
            }
            if (pfind->rnode) {
                pfind->rnode->pnode = pfind;
            }
            free(pdelete);
            //如果原节点右父节点,则删除的不是根节点
            if (pfind->pnode) {
                return proot;
            }
            else {
                return pfind;
            }
        }
        else {
            //做值的交换,然后递归删除pfind
            pdelete->val = pfind->val;
            treeDelete(pdelete, pfind);
            return proot;
        }
    }
    else if (pdelete->rnode) {

        pfind = treeMin(pdelete->rnode);

        //最大值为欲删除节点的左节点
        if (pfind == pdelete->rnode) {

            pfind->pnode = pdelete->pnode;//建立子父联系
            pfind->lnode = pdelete->lnode;//建立右子树的关系【这种情况是没有右子树的(pfind == pdelete->rnode)】
            if (pfind->pnode) {

                if (pdelete->pnode->lnode == pdelete) {
                    pdelete->pnode->lnode = pfind;//建立父子联系

                }
                else {
                    pdelete->pnode->rnode = pfind;//建立父子联系

                }
            }
            free(pdelete);
            //如果原节点有父节点,则删除的不是根节点
            if (pfind->pnode) {
                return proot;
            }
            else {
                return pfind;
            }
        }
        else {
            //做值的交换,然后递归删除pfind
            pdelete->val = pfind->val;
            treeDelete(pdelete, pfind);
            return proot;
        }
    }
    else {
        if (pdelete->pnode) {
            if (pdelete->pnode->lnode==pdelete) {
                pdelete->pnode->lnode = NULL;
            }
            else {
                pdelete->pnode->rnode = NULL;
            }
            //欲删除的节点既没有左节点也没有右节点,直接返回
            free(pdelete);
            return proot;
        }
        else {
            free(pdelete);
            return NULL;
        }

    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值