在街上看见一个人像你,我瞬间特别紧张,渴望是你,又害怕是你,直到看清不是你,我庆幸不是你,有遗憾不是你。。。

----  网易云热评

一、链表

1、link.c文件内容

#include <stdlib.h>#include "01link.h"//链表的初始化函数void link_init(link *p_link) {    p_link->head.p_next = &p_link->tail;   //头节点向后指向尾节点    p_link->tail.p_next = NULL;    //尾节点里的指针设置为空指针    p_link->tail.p_prev = &p_link->head;  //尾节点向前指向头节点    p_link->head.p_prev = NULL;    //头节点里向前的指针设置为空指针    p_link->p_cur = NULL;    //链表没有处于遍历状态}//链表的清理函数void link_deinit(link *p_link) {    node *p_first = NULL, *p_mid = NULL, *p_last = NULL;    p_link->p_cur = NULL;      //链表没有处于遍历状态    //每次循环删除头节点后面的有效节点    while (p_link->head.p_next != &p_link->tail) {   //头节点后面不是尾节点        //把三个指针指向链表最前面的        //三个节点        p_first = &p_link->head;        p_mid = p_first->p_next;        p_last = p_mid->p_next;        //把p_mid指针指向的节点从链式物理        //结构里摘出来        p_first->p_next = p_last;        p_last->p_prev = p_first;        //释放p_mid指针指向的节点        free(p_mid);        p_mid = NULL;    }}//获得链表里数字个数的函数int link_size(const link *p_link) {    int cnt = 0;    const node *p_tmp = NULL;    //编写for循环统计链表里的有效节点个数    for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) {        const node *p_first = p_tmp;        const node *p_mid = p_first->p_next;   //从第一个有效节点一直指到尾节点        const node *p_last = p_mid->p_next;        if (p_mid != &p_link->tail) {    //p_mid指针不是指向尾节点就一定指向一个有效节点            cnt++;        }    }    return cnt;}//判断链表是否空的函数int link_empty(const link *p_link) {    return p_link->head.p_next == &p_link->tail;  //头节点后面就是尾节点就表示链表是空的}//在链表最后插入新数字的功能int link_append(link *p_link, int val) {    node *p_first = NULL, *p_mid = NULL, *p_last = NULL;    node *p_node = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    p_node = (node *)malloc(sizeof(node));   //动态分配节点记录新加入的数字    if (!p_node) {        //动态分配失败        return 0;    }    p_node->val = val;     //把新数字记录到动态分配节点里    p_node->p_next = NULL;    p_node->p_prev = NULL;    //让p_mid指针指向尾节点(p_first和p_mid中间就是要插入的位置)    p_first = p_link->tail.p_prev;   //p_first指向最后一个有效节点    p_mid = p_first->p_next;    p_last = p_mid->p_next;    //把新节点插入到p_first和p_mid中间    p_first->p_next = p_node;    p_node->p_next = p_mid;    p_mid->p_prev = p_node;    p_node->p_prev = p_first;    return 1;}/*int link_append(link *p_link, int val) {    node *p_tmp = NULL;    node *p_node = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    p_node = (node *)malloc(sizeof(node));   //动态分配节点用来记录要加入的数字    if (!p_node) {        //动态分配内存失败的情况        return 0;    }    p_node->val = val;    //把要插入的数字记录到动态分配的节点里    p_node->p_next = NULL;    p_node->p_prev = NULL;    //编写for循环依次处理链表里所有可插入的位置    //直到找到最后的可插入位置    for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) {        node *p_first = p_tmp;        node *p_mid = p_first->p_next;        node *p_last = p_mid->p_next;        if (p_mid == &p_link->tail) {    //p_mid指针指向尾节点的时候p_first和p_mid中间就是最后的可插入位置            //把新节点插入到p_first和p_mid中间            p_first->p_next = p_node;            p_node->p_next = p_mid;            p_mid->p_prev = p_node;            p_node->p_prev = p_first;            break;        }    }    return 1;}*///在链表开头插入新数字的函数int link_add_head(link *p_link, int val) {    node *p_first = NULL, *p_mid = NULL, *p_last = NULL;    node *p_node = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    p_node = (node *)malloc(sizeof(node));    if (!p_node) {        return 0;    }    p_node->val = val;    p_node->p_next = NULL;    p_node->p_prev = NULL;    //让三个节点指针指向链表最前面的三个节点    //p_first和p_mid中间的位置就是最前面    //的可插入位置    p_first = &p_link->head;    p_mid = p_first->p_next;    p_last = p_mid->p_next;    //把新节点插入到p_first和p_mid中间    p_first->p_next = p_node;    p_node->p_next = p_mid;    p_mid->p_prev = p_node;    p_node->p_prev = p_first;    return 1;}//按照从小到大的顺序在链表里插入数字的函数int link_insert(link *p_link, int val) {    node *p_tmp = NULL;    node *p_node = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    p_node = (node *)malloc(sizeof(node));    if (!p_node) {        return 0;    }    p_node->val = val;    p_node->p_next = NULL;    p_node->p_prev = NULL;    //编写for循环找到要插入的位置    for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) {        node *p_first = p_tmp;        node *p_mid = p_first->p_next;        node *p_last = p_mid->p_next;        if (p_mid == &p_link->tail /*新数字比原来的所有数字都大,新节点应该插入到尾节点的前面*/ || p_mid->val > val /*p_mid指针指向节点里的数字比新数字大,新节点应该插入到p_first和p_mid中间*/) {            //把新节点插入到p_first和p_mid中间            p_first->p_next = p_node;            p_node->p_next = p_mid;            p_mid->p_prev = p_node;            p_node->p_prev = p_first;            break;        }    }    return 1;}//删除最后一个数字的函数int link_remove_tail(link *p_link) {    node *p_first = NULL, *p_mid = NULL, *p_last = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    if (p_link->head.p_next == &p_link->tail) {   //头节点的后面就是尾节点        //链表是空的,不存在最后一个数字        return 0;    }    //让三个节点指针指向链表最后的三个节点    p_last = &p_link->tail;    p_mid = p_last->p_prev;    //p_mid指针指向最后一个有效节点    p_first = p_mid->p_prev;    //把p_mid指针指向的节点从链式物理结构里    //摘出来    p_first->p_next = p_last;    p_last->p_prev = p_first;    free(p_mid);    //释放p_mid指针指向的节点    p_mid = NULL;    return 1;}/*int link_remove_tail(link *p_link) {    node *p_tmp = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    //编写for循环找到最后一个数字所在    //的节点    for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) {        node *p_first = p_tmp;        node *p_mid = p_first->p_next;        node *p_last = p_mid->p_next;        if (p_last == &p_link->tail) {    //p_last指针指向尾节点的时候p_mid指针应该指向最后一个有效节点            //首先把p_mid指针指向的节点            //从链式物理结构中摘出来            p_first->p_next = p_last;            p_last->p_prev = p_first;            free(p_mid);     //释放p_mid指针指向的节点            p_mid = NULL;            return 1;        }    }    return 0;}*///从链表里删除最前面数字的函数int link_remove_head(link *p_link) {    node *p_first = NULL, *p_mid = NULL, *p_last = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    if (p_link->head.p_next == &p_link->tail) {        //头节点后面就是尾节点表示链表是空的        return 0;    }    //让三个节点指针指向链表最前面的三个节点    p_first = &p_link->head;    p_mid = p_first->p_next;   //p_mid指针指向第一个有效节点    p_last = p_mid->p_next;    //把p_mid指针指向的节点从链式物理结构里    //摘出来    p_first->p_next = p_last;    p_last->p_prev = p_first;    free(p_mid);   //释放p_mid指针指向的节点    p_mid = NULL;    return 1;}//删除链表中间某个数字的函数int link_remove(link *p_link, int val/*要删除的数字*/) {    node *p_tmp = NULL;    p_link->p_cur = NULL;    //结束遍历过程(退出遍历状态)    //编写for循环找到要删除的节点    for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) {        node *p_first = p_tmp;        node *p_mid = p_first->p_next;        node *p_last = p_mid->p_next;        if (p_mid != &p_link->tail/*p_mid指针不是指向尾节点*/ && p_mid->val == val/*p_mid指针指向节点里的数字就是要删除的数字*/) {            //把p_mid指针指向的节点从链式物理结构里摘出来            p_first->p_next = p_last;            p_last->p_prev = p_first;            free(p_mid);     //释放p_mid指针指向的节点            p_mid = NULL;            return 1;        }    }    return 0;}//获得链表里最后一个数字的函数int link_get_tail(const link *p_link, int *p_val) {    const node *p_first = NULL, *p_mid = NULL, *p_last = NULL;    if (p_link->head.p_next == &p_link->tail) {  //头节点后面就是尾节点        //链表是空的,无法获得最后一个数字        return 0;    }    //让三个节点指针指向链表最后的三个节点    p_last = &p_link->tail;    p_mid = p_last->p_prev;    //p_mid指针指向最后一个有效节点    p_first = p_mid->p_prev;    *p_val = p_mid->val;     //把p_mid指针指向节点里的数字传递给调用函数    return 1;}#if   0int link_get_tail(const link *p_link, int *p_val/*把得到的数字传递给调用函数*/) {    const node *p_tmp = NULL;    //编写for循环找到最后一个有效节点    for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) {        const node *p_first = p_tmp;        const node *p_mid = p_first->p_next;        const node *p_last = p_mid->p_next;        if (p_last == &p_link->tail/*p_last指针指向尾节点的时候p_mid指针应该指向最后一个有效节点*/) {            *p_val = p_mid->val;    //把p_mid指针指向的存储区里的数字传递给调用函数            return 1;        }    }    return 0;}#endif//获得最前面数字的函数int link_get_head(const link *p_link, int *p_val) {    const node *p_first = NULL, *p_mid = NULL, *p_last = NULL;    if (p_link->head.p_next == &p_link->tail) {        //头结点后面就是尾节点表示链表是空的        return 0;    }    //让三个节点指针指向链表最前面的三个节点    p_first = &p_link->head;    p_mid = p_first->p_next;   //p_mid指针指向第一个有效节点    p_last = p_mid->p_next;    *p_val = p_mid->val;    //把p_mid指针指向的节点里的数字传递给调用函数    return 1;}//根据编号获得数字的函数int link_get(const link *p_link, int *p_val, int sn/*给定的编号*/) {    int cnt = 0;    const node *p_tmp = NULL;    //编写for循环找到编号sn对应的节点    for (p_tmp = &p_link->head;p_tmp != &p_link->tail;p_tmp = p_tmp->p_next) {        const node *p_first = p_tmp;        const node *p_mid = p_first->p_next;        const node *p_last = p_mid->p_next;        if (p_mid != &p_link->tail/*p_mid指针不是指向尾节点*/ && cnt == sn/*cnt是p_mid指针指向节点的编号,cnt等于sn表示p_mid指针指向的节点就是要找的节点*/) {            *p_val = p_mid->val;    //把p_mid指针指向的节点里的数字传递给调用函数            return 1;        }        cnt++;    }    return 0;}//让链表开始从前向后遍历的函数void link_begin(link *p_link) {    p_link->p_cur = &p_link->head;   //把头结点作为上一次操作的节点记录下来}//在从前向后遍历过程中获得下一个数字的函数int link_next(link *p_link, int *p_val) {    if (!p_link->p_cur) {        //排除没有处于遍历状态的情况        return 0;    }    p_link->p_cur = p_link->p_cur->p_next;   //找到这次要操作的节点并记录下来    if (p_link->p_cur == &p_link->tail) {        //这次要操作的节点如果是尾节点就表示已经处理完链表里的所有节点        p_link->p_cur = NULL;   //结束遍历过程        return 0;    }    else {        *p_val = p_link->p_cur->val;    //把这次要操作节点里的数字传递给调用函数        return 1;    }}//开始从后向前遍历链表里的所有节点void link_rbegin(link *p_link) {    p_link->p_cur = &p_link->tail;   //把尾节点作为上次操作的节点记录下来,下次操作的一定是尾节点前面的节点}//在从后向前遍历过程中获得前一个数字的函数int link_prev(link *p_link, int *p_val) {    if (!p_link->p_cur) {        //如果没有处于遍历状态就结束函数        return 0;    }    p_link->p_cur = p_link->p_cur->p_prev;   //找到这次要操作的节点并记录下来    if (p_link->p_cur == &p_link->head) {        //如果这次要操作的节点是头结点        //就表示这次遍历过程结束了        p_link->p_cur = NULL;   //结束遍历过程        return 0;    }    else {        *p_val = p_link->p_cur->val;   //把当前操作节点里的数字传递给调用函数        return 1;    }}

2、link.h文件内容

#ifndef           __01LINK_H__#define           __01LINK_H__typedef struct node {    int val;    struct node *p_prev;    //指向前一个节点    struct node *p_next;    //指向后一个节点} node;    //代表节点的结构体typedef struct {    node head;    //头节点    node tail;    //尾节点    node *p_cur;  //记录遍历过程中上一次操作的节点} link;    //代表链表的结构体//链表的初始化函数void link_init(link *);//链表的清理函数void link_deinit(link *);//获得链表里数字个数的函数int link_size(const link *);//判断链表是否空的函数int link_empty(const link *);//在链表最后插入新数字的功能int link_append(link *, int );//在链表开头插入新数字的函数int link_add_head(link *, int );//按照从小到大的顺序在链表里插入数字的函数int link_insert(link *, int );//删除最后一个数字的函数int link_remove_tail(link *);//从链表里删除最前面数字的函数int link_remove_head(link *);//删除链表中间某个数字的函数int link_remove(link *, int /*要删除的数字*/);//获得链表里最后一个数字的函数int link_get_tail(const link *, int */*把得到的数字传递给调用函数*/);//获得最前面数字的函数int link_get_head(const link *, int *);//根据编号获得数字的函数int link_get(const link *, int *, int /*给定的编号*/);//开始从前向后遍历链表的函数void link_begin(link *);//在从前向后遍历链表的过程中获得下一个数字的函数int link_next(link *, int *);//开始从后向前遍历链表的函数void link_rbegin(link *);//在从后向前遍历链表的过程中获得前一个数字的函数int link_prev(link *, int *);#endif           //__01LINK_H__

3、link主函数内容

#include <stdio.h>#include "01link.h"int main() {    int val = 0, size = 0, num = 0;    link lnk = {0};    link_init(&lnk);    link_add_head(&lnk, 50);    link_add_head(&lnk, 30);    link_append(&lnk, 80);    link_append(&lnk, 100);    //以上四个数字按照从小到大的顺序排列    link_insert(&lnk, 60);    link_insert(&lnk, 20);    link_insert(&lnk, 40);    link_insert(&lnk, 90);    link_insert(&lnk, 70);    link_insert(&lnk, 10);    link_remove_head(&lnk);    link_remove_tail(&lnk);    link_remove(&lnk, 50);    link_get_head(&lnk, &val);    printf("最前面的数字是%d\n", val);    link_get_tail(&lnk, &val);    printf("最后面的数字是%d\n", val);    size = link_size(&lnk);    //获得链表里的数字 个数并记录到size变量里    for (num = 0;num <= size - 1;num++) {        link_get(&lnk, &val, num);        printf("%d ", val);    }    printf("\n");    link_begin(&lnk);     //把链表设置成从前向后的遍历状态    while (1) {        if (!link_next(&lnk, &val)) {   //在从前向后遍历过程中获得下一个数字            //如果不能获得下一个数字就可以            //结束循环了            break;        }        printf("%d ", val);    }    printf("\n");    link_rbegin(&lnk);    //把链表设置成从后向前遍历的状态    while (1) {        if (!link_prev(&lnk, &val)) {    //在从后向前遍历过程中获得前一个数字            //如果无法继续获得数字就结束循环            break;        }        printf("%d ", val);    }    printf("\n");    link_deinit(&lnk);    return 0;}运行结果:最前面的数字是20最后面的数字是9020 30 40 60 70 80 9020 30 40 60 70 80 9090 80 70 60 40 30 20

二、栈操作

1、stack.c文件内容

#include "01stack.h"//栈的初始化函数void stack_init(stack *p_stack/*指向调用函数提供的一个代表栈的结构体存储区*/) {    p_stack->qty = 0;    //表示栈里没有数字}//栈的清理函数void stack_deinit(stack *p_stack) {    p_stack->qty = 0;    //数字个数设置为0就表示把所有数字都删除了}//获得数字个数的函数int /*得到的数字个数*/stack_size(const stack *p_stack) {    return p_stack->qty;}//判断栈是否空的函数int /*返回值为真表示栈是空的,否则栈不是空的*/stack_empty(const stack *p_stack) {    return !p_stack->qty;}//判断栈是不是满的函数int /*返回值为真表示栈是满的,否则栈不是满的*/stack_full(const stack *p_stack) {    return p_stack->qty >= SIZE;}//向栈里加入数字的函数int /*返回值为真表示加入成功,否则加入失败*/stack_push(stack *p_stack, int val/*表示要加入的数字*/) {    if (p_stack->qty >= SIZE) {        //栈已经满了        return 0;    }    p_stack->buf[p_stack->qty] = val;   //把新数字放在数组里以qty做下标的存储区里    p_stack->qty++;    //把栈里的数字个数加一    return 1;}//从栈里获得一个数字的函数(同时把数字从栈里删除)int /*返回值为真表示获得数字成功,为假表示失败*/stack_pop(stack *p_stack, int *p_val/*把得到的数字记录到这个指针指向的整数类型存储区里*/) {    if (!p_stack->qty) {        //处理栈为空的情况        return 0;    }    *p_val = p_stack->buf[p_stack->qty - 1];    //qty - 1做下标的存储区里放的就是最后一个数字,把这个数字赋值给整数指针形参指向的存储区    p_stack->qty--;     //数字个数减一就相当于把最后一个数字删除    return 1;}//从栈里获得最后一个数字的函数(不会从栈里删除数字)int /*返回值为真表示成功获得数字,为假表示没有获得数字*/stack_top(const stack *p_stack, int *p_val) {    if (!p_stack->qty) {        //处理栈为空的情况        return 0;    }    *p_val = p_stack->buf[p_stack->qty - 1];    return 1;}

2、stack.h文件内容

#ifndef          __STACK_H__#define          __STACK_H__typedef struct {    int buf[SIZE];    //前面的数字记录到小下标的存储区里,后面的数字记录到大下标的存储区里    int qty;          //记录栈里的数字个数} stack;    //用来代表栈的结构体类型//栈的初始化函数void stack_init(stack * /*指向调用函数提供的一个代表栈的结构体存储区*/);//栈的清理函数void stack_deinit(stack *);//获得数字个数的函数int /*得到的数字个数*/stack_size(const stack *);//判断栈是否空的函数int /*返回值为真表示栈是空的,否则栈不是空的*/stack_empty(const stack *);//判断栈是不是满的函数int /*返回值为真表示栈是满的,否则栈不是满的*/stack_full(const stack *);//向栈里加入数字的函数int /*返回值为真表示加入成功,否则加入失败*/stack_push(stack *, int /*表示要加入的数字*/);//从栈里获得一个数字的函数(同时把数字从栈里删除)int /*返回值为真表示获得数字成功,为假表示失败*/stack_pop(stack *, int * /*把得到的数字记录到这个指针指向的整数类型存储区里*/);//从栈里获得最后一个数字的函数(不会从栈里删除数字)int /*返回值为真表示成功获得数字,为假表示没有获得数字*/stack_top(const stack *, int *);#endif     //__STACK_H__

3、stack主函数

#include <stdio.h>#include "01stack.h"int main() {    int val = 0;    stack stk = {0};    stack_init(&stk);    printf("数字个数是%d\n", stack_size(&stk)/*获得栈里数字个数*/);    printf("判断空的结果是%d\n", stack_empty(&stk));   //判断栈是否空    printf("判断满的结果是%d\n", stack_full(&stk));    //判断栈是否满    stack_push(&stk, 10);    stack_push(&stk, 20);    stack_push(&stk, 30);    printf("数字个数是%d\n", stack_size(&stk)/*获得栈里数字个数*/);    printf("判断空的结果是%d\n", stack_empty(&stk));   //判断栈是否空    printf("判断满的结果是%d\n", stack_full(&stk));    //判断栈是否满    stack_push(&stk, 40);    stack_push(&stk, 50);    printf("数字个数是%d\n", stack_size(&stk)/*获得栈里数字个数*/);    printf("判断空的结果是%d\n", stack_empty(&stk));   //判断栈是否空    printf("判断满的结果是%d\n", stack_full(&stk));    //判断栈是否满    stack_top(&stk, &val);   //从栈里获得最后一个数字    printf("最后一个数字是%d\n", val);    while (1) {        if (!stack_pop(&stk, &val)) {   //从栈里获得一个数字并把数字从栈里删除            //当不能从栈里获得数字的时候            break;        }        printf("%d ", val);    }    printf("\n");    printf("数字个数是%d\n", stack_size(&stk)/*获得栈里数字个数*/);    printf("判断空的结果是%d\n", stack_empty(&stk));   //判断栈是否空    printf("判断满的结果是%d\n", stack_full(&stk));    //判断栈是否满    stack_deinit(&stk);    return 0;}运行结果:数字个数是0判断空的结果是1判断满的结果是0数字个数是3判断空的结果是0判断满的结果是0数字个数是5判断空的结果是0判断满的结果是0最后一个数字是5050 40 30 20 10数字个数是0判断空的结果是1判断满的结果是0

三、树

1、tree.c内容

#include <stdlib.h>#include "tree.h"//树的初始化函数void tree_init(tree *p_tree) {    p_tree->p_node = NULL;    //把方块里的指针设置成空指针形成一个空树(没有圆圈的树)}//树的清理函数void tree_deinit(tree *p_tree) {    //清理函数必须采用后序遍历方式处理    if (!(p_tree->p_node)) {        //处理树里没有节点的情况        return ;    }    tree_deinit(&(p_tree/*指向最上面的方块*/->p_node/*指向最大的圆圈*/->left/*代表左子树的方块*/));     //清理左子树    tree_deinit(&(p_tree->p_node->right));    //清理右子树    free(p_tree->p_node);    //释放最大的圆圈    p_tree->p_node = NULL; //把最上面方块里的指针设置成空指针}//在有序二叉树里查找某个数字应该插入位置的函数tree * /*用一个方块的地址作为返回值表示找到的位置*/tree_search(const tree *p_tree, int val) {    //采用递归函数实现查找效果    if (!p_tree->p_node) {        //处理树里没有节点的情况        return (tree *)p_tree;    //把树里唯一的方块作为返回值传递给调用函数    }    //采用分支在根节点,左子树和右子树里    //挑一部分继续查找    if (p_tree->p_node->val == val) {        //根节点里的数字就是要找的数字        return (tree *)p_tree;   //用根节点上面的方块表示找到的位置    }    else if (p_tree->p_node->val > val) {        //根节点里的数字比要找的数字大就        //应该在左子树里继续查找        return tree_search(&(p_tree->p_node->left), val);    //把左子树方块的地址作为第一个参数递归调用查找函数就可以在左子树里继续查找    }    else {        return tree_search(&(p_tree->p_node->right), val);    //把右子树方块的地址作为第一个参数递归调用查找函数表示在右子树里继续查找    }}//在有序二叉树里插入数字的函数int tree_insert(tree *p_tree, int val) {    node *p_node = NULL;    tree *p_pos = tree_search(p_tree, val);    //在有序二叉树里查找要插入的位置    if (p_pos->p_node) {        //如果找到的方块下面有一个圆圈那这个        //圆圈里就放着要插入的数字        return 0;    }    p_node = (node *)malloc(sizeof(node));   //动态分配节点记录要插入的数字    if (!p_node) {        //动态分配失败的情况        return 0;    }    p_node->val = val;       //把新数字记录到动态分配节点里    p_node->left.p_node = NULL;    //动态分配节点没有左子节点    p_node->right.p_node = NULL;   //动态分配节点也没有右子节点    p_pos->p_node = p_node;     //把新节点挂在找到的方块下面    return 1;}//以中序遍历方式处理树里每个节点的函数void tree_miter(const tree *p_tree, pfunc_t p_func) {    if (!p_tree->p_node) {        //处理树为空的情况        return ;    }    tree_miter(&(p_tree->p_node->left), p_func);   //把左子树方块的地址作为参数递归调用tree_miter函数处理左子树里的所有节点    p_func(p_tree->p_node->val);   //处理根节点里的数字    tree_miter(&(p_tree->p_node->right), p_func);  //把右子树方块的地址作为参数递归调用tree_miter函数处理右子树里的所有节点}

2、tree.h内容

#ifndef           __TREE_H__#define           __TREE_H__struct node;    //告诉编译器存在一个叫做node的结构体类型typedef struct {    struct node *p_node;} tree;typedef struct node {    int val;    tree left;     //左子树    tree right;    //右子树} node;typedef void (*pfunc_t)(int);    //创建函数指针类型名称,这种类型的函数指针都可以指向print_cb函数//树的初始化函数void tree_init(tree *);//树的清理函数void tree_deinit(tree *);//在有序二叉树里插入数字的函数int tree_insert(tree *, int );//以中序遍历方式处理树里每个节点的函数void tree_miter(const tree *, pfunc_t );#endif          //__01TREE_H__

3、主函数内容

#include <stdio.h>#include "tree.h"void print_cb(int val) {    printf("%d ", val);}int main() {    tree tr = {0};    tree_init(&tr);    tree_insert(&tr, 50);    tree_insert(&tr, 25);    tree_insert(&tr, 75);    tree_insert(&tr, 13);    tree_insert(&tr, 37);    tree_insert(&tr, 67);    tree_insert(&tr, 88);    tree_insert(&tr, 7);    tree_miter(&tr, print_cb);   //把print_cb函数作为第二个参数调用中序遍历函数把有序二叉树里所有数字按照从小到大的顺序显示在屏幕上    printf("\n");    tree_deinit(&tr);    return 0;}

欢迎关注公众号:顺便编点程

C语言(链表、栈、树)_链表