2022版王道数据结构算法题C语言代码实现-第5章-树与二叉树

概述

这是2022版王道数据结构的第5章——树与二叉树的算法大题的C语言代码实现,主要分为二叉树树与二叉树的应用三部分。代码基本都经过了简单的测试,应该不会有太大问题。
编译环境为gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0,文件目录结构如下:

ch5
├── 5-3-binaryTree.c
├── 5-4-tree.c
├── 5-5-application.c
├── application_test.c
├── binaryTree_test.c
├── queueAndStack.c
└── tree_test.c

queueAndStack.c中实现了自定义的队列和栈的结构及其操作集,也定义了二叉树节点类型如下:

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

#define BinTreeElemType char
#define StackElemType BinTree
#define QueueElemType BinTree
#define NOINFO '0'

struct TreeNode {
    BinTreeElemType data;
    struct TreeNode* left;
    struct TreeNode* right;
};
typedef struct TreeNode TreeNode;
typedef struct TreeNode* BinTree;

二叉树

在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述

代码实现

#include <string.h>

#include "queueAndStack.c"

void visit(BinTree p) {
    printf("%c ", p->data);
}

//3-后序非递归遍历二叉树
void postOrderIteratively(BinTree t) {
    if (t != NULL) {
        Stack s = CreateStack();
        BinTree r = NULL;
        BinTree p = t;
        while (p || !StackEmpty(s)) {
            if (p) {
                Push(s, p);
                p = p->left;
            } else {
                Top(s, &p);
                if (p->right && p->right != r) {
                    p = p->right;
                } else {
                    Pop(s, &p);
                    visit(p);
                    r = p;
                    p = NULL;
                }
            }
        }
        DestoryStack(s);
    }
}

//4-逆序层序遍历
void invertLevelOrder(BinTree t) {
    if (t) {
        BinTree p = t;
        Queue q = CreateQueue();
        Stack s = CreateStack();
        EnQueue(q, p);
        while (!QueueEmpty(q)) {
            DeQueue(q, &p);
            Push(s, p);
            if (p->left)
                EnQueue(q, p->left);
            if (p->right)
                EnQueue(q, p->right);
        }
        while (!StackEmpty(s)) {
            Pop(s, &p);
            visit(p);
        }
        DestoryStack(s);
        DestoryQueue(q);
    }
}

//5-非递归求二叉树高度
int Height(BinTree t) {
    if (t == NULL)
        return 0;
    int front = -1;
    int rear = -1;
    int level = 0;
    int last = 0;
    BinTree p = t;
    BinTree q[64];
    q[++rear] = t;
    while (front < rear) {
        p = q[++front];
        if (p->left)
            q[++rear] = p->left;
        if (p->right)
            q[++rear] = p->right;
        if (front == last) {
            level++;
            last = rear;
        }
    }
    return level;
}

//6-从先序和中序遍历序列确定一棵二叉树
BinTree PreOrderAndInOrderCreate(BinTreeElemType A[], int la, int ra, BinTreeElemType B[], int lb, int rb) {
    int i = 0;
    BinTree root = malloc(sizeof(struct TreeNode));
    root->data = A[la];
    for (i = 0; root->data != B[i]; ++i)
        ;
    int llen = i - lb;
    int rlen = rb - i;
    if (llen)
        root->left = PreOrderAndInOrderCreate(A, la + 1, la + llen, B, lb, lb + llen - 1);
    else
        root->left = NULL;
    if (rlen)
        root->right = PreOrderAndInOrderCreate(A, ra - rlen + 1, ra, B, rb - rlen + 1, rb);
    else
        root->right = NULL;
    return root;
}

//7-判断是否是完全二叉树
bool isComplete(BinTree t) {
    if (t == NULL)
        return true;
    Queue q = CreateQueue();
    BinTree p = t;
    EnQueue(q, p);
    while (!QueueEmpty(q)) {
        DeQueue(q, &p);
        if (p) {
            EnQueue(q, p->left);
            EnQueue(q, p->right);
        } else {
            //一旦层序遍历到了一个空节点,则它之后的节点必然全是空的,否则return false
            while (!QueueEmpty(q)) {
                DeQueue(q, &p);
                if (p)
                    return false;
            }
        }
    }
    DestoryQueue(q);
    return true;
}

//8-求树中degree==2的节点的数量,纯递归
int DoubleSonNodes(BinTree t) {
    if (t == NULL) {
        return 0;
    } else if (t->left && t->right) {
        return 1 + DoubleSonNodes(t->left) + DoubleSonNodes(t->right);
    } else {
        return DoubleSonNodes(t->left) + DoubleSonNodes(t->right);
    }
}

//9-交换左右子树
void swapLeftRight(BinTree t) {
    if (t) {
        //采用后序遍历的策略,待左右子树都交换完成后,再交换自身
        swapLeftRight(t->left);
        swapLeftRight(t->right);
        BinTree temp = t->left;
        t->left = t->right;
        t->right = temp;
    }
}

//10-寻找先序遍历序列中第N个节点,约定若为空返回'#'
#define NOTFOUND '#'
int i = 1;
BinTreeElemType NthPreNode(BinTree t, int N) {
    if (t == NULL)
        return NOTFOUND;
    if (i == N)
        return t->data;
    i++;
    BinTreeElemType ch = NthPreNode(t->left, N);
    if (ch != NOTFOUND)
        return ch;
    ch = NthPreNode(t->right, N);
    return ch;
}

void deleteSubTree(BinTree t) {
    if (t) {
        deleteSubTree(t->left);
        deleteSubTree(t->right);
        free(t);
    }
}

//11-删除二叉树每个元素值为X的节点
void deleteAllX(BinTree t, BinTreeElemType x) {
    if (t == NULL)
        return;
    if (t->data == x) {
        deleteSubTree(t);
        return;
    }
    Queue q = CreateQueue();
    BinTree p = t;
    EnQueue(q, p);
    while (!QueueEmpty(q)) {
        DeQueue(q, &p);
        if (p->left) {
            if (p->left->data == x) {
                deleteSubTree(p->left);
                p->left = NULL;
            } else {
                EnQueue(q, p->left);
            }
        }

        if (p->right) {
            if (p->right->data == x) {
                deleteSubTree(p->right);
                p->right = NULL;
            } else {
                EnQueue(q, p->right);
            }
        }
    }

    DestoryQueue(q);
}

//12-打印x的所有祖先
void printXAncestors(BinTree t, BinTreeElemType x) {
    if (t == NULL)
        return;
    BinTree p = t;
    BinTree r = NULL;
    Stack s = CreateStack();
    while (!StackEmpty(s) || p != NULL) {
        if (p) {
            Push(s, p);
            p = p->left;
        } else {
            Top(s, &p);
            if (p->right != NULL && p->right != r) {
                p = p->right;
            } else {
                Pop(s, &p);
                //visit
                if (p->data == x) {
                    //当前访问节点为x,则弹空栈中x的所有祖先并打印
                    while (!StackEmpty(s)) {
                        Pop(s, &p);
                        printf("%c\n", p->data);
                    }
                    return;
                }
                r = p;
                p = NULL;
            }
        }
    }
    DestoryStack(s);
}

//13-寻找p和q的公共祖先,不妨假设p在q的左边
BinTree CommonAncestor(BinTree t, BinTree p, BinTree q) {
    if (t == NULL || p == NULL || q == NULL)
        return NULL;
    int last = -1;
    BinTree curr = t;
    BinTree r = NULL;
    BinTree dump[64];  //转储遇到p时的栈,里面是p的所有祖先
    Stack s = CreateStack();
    while (!StackEmpty(s) || curr != NULL) {
        if (curr) {
            Push(s, curr);
            curr = curr->left;
        } else {
            Top(s, &curr);
            if (curr->right && curr->right != r) {
                curr = curr->right;
            } else {
                Pop(s, &curr);
                //visit
                if (curr == p) {
                    //转储并复原s
                    BinTree t;
                    while (!StackEmpty(s)) {
                        Pop(s, &t);
                        dump[++last] = t;
                    }
                    for (int i = last; i >= 0; --i) {
                        Push(s, dump[i]);
                    }
                }
                if (curr == q) {
                    BinTree t;
                    //逐个比对此时栈中的元素和dump中的元素
                    while (!StackEmpty(s)) {
                        Pop(s, &t);
                        for (int i = 0; i <= last; ++i) {
                            if (dump[i] == t) {
                                return t;
                            }
                        }
                    }
                }
                r = curr;
                curr = NULL;
            }
        }
    }
    //应该是多余的,但是不返回一个值编译器会报警告
    //老强迫症了
    return t;
    DestoryStack(s);
}

//14-求二叉树的宽度
int width(BinTree t) {
    if (t == NULL)
        return 0;
    struct {
        BinTree data[128];
        int level[128];
        int front;
        int rear;
    } Que;
    memset(&Que, 0, sizeof(Que));
    Que.front = Que.rear = -1;

    BinTree p = t;
    int k, max, n;

    Que.data[++Que.rear] = p;
    Que.level[Que.rear] = 1;

    while (Que.front < Que.rear) {
        p = Que.data[++Que.front];
        k = Que.level[Que.front];
        if (p->left) {
            Que.data[++Que.rear] = p->left;
            Que.level[Que.rear] = k + 1;
        }
        if (p->right) {
            Que.data[++Que.rear] = p->right;
            Que.level[Que.rear] = k + 1;
        }
    }
    int i = 0;
    while (i <= Que.rear) {
        n = 0;
        while (i <= Que.rear && Que.level[i] == k) {
            n++;
            i++;
        }
        k = Que.level[i];
        if (n > max)
            max = n;
    }
    return max;
}

//15-对一棵满二叉树,已知先序序列,求后序序列
void pre2post(BinTreeElemType pre[], int lPre, int rPre, BinTreeElemType post[], int lPost, int rPost) {
    int half;
    if (rPre >= lPre) {
        post[rPost] = pre[lPre];
        half = (rPre - lPre) / 2;
        pre2post(pre, lPre + 1, lPre + half, post, lPost, lPost + half - 1);
        pre2post(pre, lPre + half + 1, rPre, post, lPost + half, rPost - 1);
    }
}

//16-将二叉树的叶节点链接成单链表
BinTree head = NULL;
BinTree rear = NULL;

BinTree inOrderLinkLeaves(BinTree bt) {
    if (bt) {
        inOrderLinkLeaves(bt->left);
        if (bt->left == NULL && bt->right == NULL) {
            if (head == NULL) {
                head = bt;
                rear = bt;
            } else {
                rear->right = bt;
                rear = rear->right;
            }
        }
        inOrderLinkLeaves(bt->right);
        rear->right = NULL;
    }
    return head;
}

//17-判断两课树是否相似
bool similar(BinTree t1, BinTree t2) {
    bool sLeft, sRight;
    if (t1 == NULL && t2 == NULL) {
        return true;
    } else if (t1 == NULL || t2 == NULL) {
        return false;
    } else {
        sLeft = similar(t1->left, t2->left);
        sRight = similar(t1->right, t2->right);
        return sLeft && sRight;
    }
}

//18-在中序线索二叉树里查找指定节点在后序中的前驱节点
#define ThreadBinTreeElemType char

//线索二叉树节点类型
struct ThreadBinTreeNode {
    ThreadBinTreeElemType data;
    struct ThreadBinTreeNode* left;
    struct ThreadBinTreeNode* right;
    int ltag;
    int rtag;
};

typedef struct ThreadBinTreeNode ThreadBinTreeNode;
typedef struct ThreadBinTreeNode* ThreadBinTree;

ThreadBinTree findPostPrevInOrderThread(ThreadBinTree t, ThreadBinTree p) {
    ThreadBinTree q;
    if (p->rtag == 0) {
        q = p->right;
    } else if (p->ltag == 0) {
        q = p->left;
    } else if (p->left == NULL) {
        q = NULL;
    } else {
        while (p->ltag == 1 && p->left != NULL) {
            p = p->left;
        }
        if (p->ltag == 0) {
            q = p->left;
        } else {
            q = NULL;
        }
    }
    return q;
}

//19-计算WPL
int WPL_preOrder(BinTree t, int deepth) {
    static int wpl = 0;
    if (t->left == NULL && t->right == NULL) {
        wpl += deepth * (t->data);
    }
    if (t->left)
        WPL_preOrder(t->left, deepth + 1);
    if (t->right)
        WPL_preOrder(t->right, deepth + 1);

    return wpl;
}

int WPL(BinTree bt) {
    return WPL_preOrder(bt, 0);
}

//20-将给定的表达式树转化为中缀表达式
void printInOrder(BinTree t, int deep) {
    if (t == NULL) {
        return;
    } else if (t->left == NULL && t->right == NULL) {
        printf("%c", t->data);
    } else {
        if (deep > 1)
            printf("(");
        printInOrder(t->left, deep + 1);
        printf("%c", t->data);
        printInOrder(t->right, deep + 1);
        if (deep > 1)
            printf(")");
    }
}

void printExpressionTree(BinTree t) {
    printInOrder(t, 1);
}

测试代码

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

#include "5-3-binaryTree.c"

void PreOrderTraversal_recursively(BinTree t, void (*visit)(BinTree x)) {
    if (t != NULL) {
        visit(t);
        PreOrderTraversal_recursively(t->left, visit);
        PreOrderTraversal_recursively(t->right, visit);
    }
}

void InOrderTraversal_recursively(BinTree t, void (*visit)(BinTree x)) {
    if (t != NULL) {
        InOrderTraversal_recursively(t->left, visit);
        visit(t);
        InOrderTraversal_recursively(t->right, visit);
    }
}

void PostOrderTraversal_recursively(BinTree t, void (*visit)(BinTree x)) {
    if (t != NULL) {
        PostOrderTraversal_recursively(t->left, visit);
        PostOrderTraversal_recursively(t->right, visit);
        visit(t);
    }
}

void LevelOrderTraversal(BinTree t, void (*visit)(BinTree x)) {
    if (t == NULL)
        return;
    Queue q = CreateQueue();
    BinTree curr = t;
    EnQueue(q, curr);
    while (!QueueEmpty(q)) {
        DeQueue(q, &curr);
        visit(curr);
        if (curr->left != NULL)
            EnQueue(q, curr->left);
        if (curr->right != NULL)
            EnQueue(q, curr->right);
    }
    DestoryQueue(q);
}

BinTree* buildBinTree(int n) {
    BinTree* arr = (BinTree*)malloc(sizeof(BinTree) * (n + 1));
    arr[0] = NULL;
    for (int i = 1; i <= n; ++i) {
        arr[i] = malloc(sizeof(struct TreeNode));
        arr[i]->data = 'A' + i - 1;
        arr[i]->left = arr[i]->right = NULL;
    }
    for (int i = 1; i <= n / 2; ++i) {
        arr[i]->left = arr[2 * i];
        arr[i]->right = arr[2 * i + 1];
    }
    return arr;
}

void DestoryBinTree(BinTree t) {
    if (t) {
        DestoryBinTree(t->left);
        DestoryBinTree(t->right);
        free(t);
    }
}

void test_postOrderIteratively() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(5);
    BinTree root = arr[1];
    postOrderIteratively(root);

    DestoryBinTree(root);
    free(arr);
    printf("\n");
}

void test_invertLevelOrder() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(25);
    BinTree root = arr[1];
    invertLevelOrder(root);

    DestoryBinTree(root);
    free(arr);
    printf("\n");
}

void test_Height() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(25);
    BinTree root = arr[1];
    int h = Height(root);
    printf("\nh=%d\n", h);

    DestoryBinTree(root);
    free(arr);
}

void test_PreOrderAndInOrderCreate() {
    printf("\n%s\n", __func__);
    char pre[11] = {'\0', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '\0'};
    char in[11] = {'\0', 'B', 'C', 'A', 'E', 'D', 'G', 'H', 'F', 'I', '\0'};
    printf("\npre:%s\n", pre + 1);
    printf("\nin:%s\n", in + 1);
    BinTree root = PreOrderAndInOrderCreate(pre, 1, 9, in, 1, 9);
    PreOrderTraversal_recursively(root, visit);
    printf("\n");
    InOrderTraversal_recursively(root, visit);
    printf("\n");

    DestoryBinTree(root);
}

void test_isComplete() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(9);
    BinTree root = arr[1];
    bool result = isComplete(root);
    printf("\nresult=%d\n", result);

    DestoryBinTree(arr[3]->left);
    arr[3]->left = NULL;
    result = isComplete(root);
    printf("\nresult=%d\n", result);

    DestoryBinTree(root);
    free(arr);
}

void test_DoubleSonNodes() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(11);
    BinTree root = arr[1];
    int result;
    result = DoubleSonNodes(root);
    printf("\nresult=%d\n", result);

    DestoryBinTree(arr[3]->left);
    DestoryBinTree(arr[5]->left);
    arr[3]->left = NULL;
    arr[5]->left = NULL;
    result = DoubleSonNodes(root);
    printf("\nresult=%d\n", result);

    DestoryBinTree(root);
    free(arr);
}

void test_swapLetfRight() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(11);
    BinTree root = arr[1];
    printf("\nbefore:\n");
    PreOrderTraversal_recursively(root, visit);
    printf("\n\n");
    LevelOrderTraversal(root, visit);
    printf("\n\n");

    swapLeftRight(root);
    printf("\nafter:\n");
    PreOrderTraversal_recursively(root, visit);
    printf("\n\n");
    LevelOrderTraversal(root, visit);
    printf("\n\n");

    DestoryBinTree(root);
    free(arr);
}

void test_NthPreNode() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(11);
    BinTree root = arr[1];

    int N = 6;
    PreOrderTraversal_recursively(root, visit);
    BinTreeElemType ret = NthPreNode(root, N);
    printf("\n%d-%c\n", N, ret);

    i = 1;
    N = 11;
    ret = NthPreNode(root, N);
    printf("\n%d-%c\n", N, ret);

    i = 1;
    N = 12;
    ret = NthPreNode(root, N);
    printf("\n%d-%c\n", N, ret);

    DestoryBinTree(root);
    free(arr);
}

void test_deleteAllX() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(11);
    BinTree root = arr[1];

    arr[5]->data = 'X';
    PreOrderTraversal_recursively(root, visit);
    printf("\n\n");
    deleteAllX(root, 'X');
    PreOrderTraversal_recursively(root, visit);
    printf("\n\n");

    DestoryBinTree(root);
    free(arr);
}

void test_printXAncestors() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(11);
    BinTree root = arr[1];

    printXAncestors(root, 'H');

    DestoryBinTree(root);
    free(arr);
}

void test_CommonAncestor() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(11);
    BinTree root = arr[1];

    BinTree p = arr[4];
    BinTree q = arr[10];
    BinTree ancestor = CommonAncestor(root, p, q);
    if (ancestor) {
        printf("\np->data=%c,q->data=%c,ancestor->data=%c\n", p->data, q->data, ancestor->data);
    }

    p = arr[3];
    ancestor = CommonAncestor(root, p, q);
    if (ancestor) {
        printf("\np->data=%c,q->data=%c,ancestor->data=%c\n", p->data, q->data, ancestor->data);
    }
}

void test_width() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(15);
    BinTree root = arr[1];

    int w = width(root);
    printf("\nw=%d\n", w);

    arr[5]->left = arr[5]->right = NULL;
    arr[6]->left = arr[6]->right = NULL;
    arr[7]->left = NULL;
    w = width(root);
    printf("\nw=%d\n", w);

    DestoryBinTree(root);
    free(arr);
}

void test_pre2post() {
    BinTreeElemType pre[] = "ABDECFG";
    BinTreeElemType post[8];
    pre2post(pre, 0, 6, post, 0, 6);
    post[8] = '\0';
    printf("\npre:%s\npost:%s\n", pre, post);
}

void test_inOrderLinkLeaves() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(15);
    BinTree root = arr[1];

    BinTree h = inOrderLinkLeaves(root);
    while (h) {
        printf("%c ", h->data);
        h = h->right;
    }
    printf("\n\n");
    //DestoryBinTree(root);
    free(arr);
}

void test_similar() {
    printf("\n%s\n", __func__);
    BinTree* arr1 = buildBinTree(15);
    BinTree root1 = arr1[1];
    BinTree* arr2 = buildBinTree(15);
    BinTree root2 = arr2[1];
    bool result;
    result = similar(root1, root2);
    printf("\nresult=%d\n", result);

    deleteSubTree(arr2[5]->right);
    arr2[5]->right = NULL;
    result = similar(root1, root2);
    printf("\nresult=%d\n", result);

    deleteSubTree(root1);
    deleteSubTree(root2);
    root1 = root2 = NULL;
    result = similar(root1, root2);
    printf("\nresult=%d\n", result);

    free(arr1);
    free(arr2);
}

void test_findPostPrevInOrderThread() {
    //这个测试不好测,省去了,考的概率不大
}

void test_WPL() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(15);
    BinTree root = arr[1];

    for (int i = 8; i <= 15; ++i) {
        arr[i]->data = i - 7;
    }
    deleteSubTree(arr[2]->right);
    arr[2]->right = NULL;

    int wpl = WPL(root);
    printf("\nwpl=%d\n", wpl);

    DestoryBinTree(root);
    free(arr);
}

void test_printExpressionTree() {
    printf("\n%s\n", __func__);
    BinTree* arr = buildBinTree(15);
    BinTree root = arr[1];

    deleteSubTree(arr[4]->left);
    arr[4]->left = NULL;
    deleteSubTree(arr[4]->right);
    arr[4]->right = NULL;

    deleteSubTree(arr[5]->left);
    arr[5]->left = NULL;
    deleteSubTree(arr[5]->right);
    arr[5]->right = NULL;

    deleteSubTree(arr[6]->left);
    arr[6]->left = NULL;
    deleteSubTree(arr[6]->left);
    arr[6]->right = NULL;

    deleteSubTree(arr[7]->left);
    arr[7]->left = NULL;

    arr[1]->data = '*';
    arr[2]->data = '+';
    arr[3]->data = '*';
    arr[4]->data = 'a';
    arr[5]->data = 'b';
    arr[6]->data = 'c';
    arr[7]->data = '-';
    arr[15]->data = 'd';

    printExpressionTree(root);
    printf("\n\n");
    DestoryBinTree(root);
    free(arr);
}

int main(int argc, char* argv[]) {
#if 0
    test_postOrderIteratively();
    test_invertLevelOrder();
    test_Height();
    test_PreOrderAndInOrderCreate();
    test_isComplete();
    test_DoubleSonNodes();
    test_swapLetfRight();
    test_NthPreNode();
    test_deleteAllX();
    test_printXAncestors();
    test_CommonAncestor();
    test_width();
    test_pre2post();
    test_inOrderLinkLeaves();
    test_similar();
    test_findPostPrevInOrderThread();
    test_WPL();
#endif
    test_printExpressionTree();
    return 0;
}

在这里插入图片描述

代码实现

#include <stdlib.h>
typedef char FCNSTreeElemType;

//5-求以孩子兄弟表示法存储的树的叶子节点总数
struct FCNSTreeNode {
    FCNSTreeElemType data;
    struct FCNSTreeNode* firstChild;
    struct FCNSTreeNode* nextSibling;
};
typedef struct FCNSTreeNode* FCNSTree;
typedef struct FCNSTreeNode FCNSTreeNode;

int countLeaves(FCNSTree t) {
    if (t == NULL) {
        return 0;
    } else if (t->firstChild == NULL) {
        //printf("%c ", t->data);
        return 1 + countLeaves(t->nextSibling);
    } else {
        return countLeaves(t->firstChild) + countLeaves(t->nextSibling);
    }
}

//6-求树的高度
int height(FCNSTree t) {
    if (t == NULL)
        return 0;
    int h_fc = height(t->firstChild);
    int h_ns = height(t->nextSibling);
    return ((h_fc + 1) > h_ns) ? (h_fc + 1) : h_ns;
}

//7-已知一颗树的层次序列及每个节点的度,构造此树的孩子-兄弟链表
FCNSTree createTree(FCNSTreeElemType e[], int degree[], int N) {
    FCNSTree nodes = (FCNSTree)malloc(sizeof(FCNSTreeNode) * N);
    int i, j, d, k = 0;
    for (i = 0; i < N; ++i) {
        nodes[i].data = e[i];
        nodes[i].firstChild = nodes[i].nextSibling = NULL;
    }
    for (i = 0; i < N; ++i) {
        d = degree[i];
        if (d) {
            k++;
            nodes[i].firstChild = &nodes[k];
            for (j = 2; j <= d; ++j) {
                k++;
                nodes[k - 1].nextSibling = &nodes[k];
            }
        }
    }
    return nodes;
}

测试代码

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

#include "5-4-tree.c"

void preOrderPrint(FCNSTree t) {
    if (t) {
        printf("%c ", t->data);
        preOrderPrint(t->firstChild);
        preOrderPrint(t->nextSibling);
    }
}

void test_countLeaves() {
    FCNSTreeNode nodes[10];
    /*
        A
        |
        B----C----D
        |    |    |
        E-F  G    H----I----J
    */
    for (int i = 0; i < 10; ++i) {
        nodes[i].data = 'A' + i;
        nodes[i].firstChild = nodes[i].nextSibling = NULL;
    }
    nodes[0].firstChild = &nodes[1];

    nodes[1].firstChild = &nodes[4];
    nodes[1].nextSibling = &nodes[2];

    nodes[2].firstChild = &nodes[6];
    nodes[2].nextSibling = &nodes[3];

    nodes[3].firstChild = &nodes[7];

    nodes[7].nextSibling = &nodes[8];
    nodes[8].nextSibling = &nodes[9];

    nodes[4].nextSibling = &nodes[5];

    int l = countLeaves(&nodes[0]);
    printf("\nl=%d\n", l);
}

void test_height() {
    /*
        A
        |
        B----C----D
        |    |    |
        E-F  G    H----I----J
    */
    FCNSTreeNode nodes[10];
    for (int i = 0; i < 10; ++i) {
        nodes[i].data = 'A' + i;
        nodes[i].firstChild = nodes[i].nextSibling = NULL;
    }
    nodes[0].firstChild = &nodes[1];

    nodes[1].firstChild = &nodes[4];
    nodes[1].nextSibling = &nodes[2];

    nodes[2].firstChild = &nodes[6];
    nodes[2].nextSibling = &nodes[3];

    nodes[3].firstChild = &nodes[7];

    nodes[7].nextSibling = &nodes[8];
    nodes[8].nextSibling = &nodes[9];

    nodes[4].nextSibling = &nodes[5];
    int h;
    h = height(&nodes[0]);
    printf("\nh=%d\n", h);

    /*
    再加上两个节点
        A
        |
        B----C----D
        |    |    |
        E-F  G    H----I----J
             |
             K
             |
             L
    */
    FCNSTreeNode* n10 = (FCNSTreeNode*)malloc(sizeof(FCNSTreeNode));
    nodes[6].firstChild = n10;
    n10->data = 'K';
    n10->nextSibling = NULL;
    FCNSTreeNode* n11 = (FCNSTreeNode*)malloc(sizeof(FCNSTreeNode));
    n11->data = 'L';
    n10->firstChild = n11;
    n11->firstChild = NULL;
    n11->nextSibling = NULL;

    //countLeaves(nodes);
    h = height(&nodes[0]);
    printf("\nh=%d\n", h);
    free(n10);
    free(n11);
}

void test_createTree() {
    /*
        A
        |
        B----C----D
        |    |    |
        E-F  G    H----I----J
    */
    int degree[10] = {3, 2, 1, 3, 0, 0, 0, 0, 0, 0};
    FCNSTreeElemType e[10];
    for (int i = 0; i < 10; ++i) {
        e[i] = 'A' + i;
    }
    FCNSTree root = createTree(e, degree, 10);
    preOrderPrint(root);
    printf("\n\n");
}

int main(int argc, char* argv[]) {
#if 0
    test_countLeaves();
    test_height();
#endif
    test_createTree();
    return 0;
}

树与二叉树的应用

在这里插入图片描述

代码实现

#include "queueAndStack.c"

//6-判断给定的二叉树是否是二叉排序树
BinTreeElemType prev = -1;
bool judgeIsBST(BinTree t) {
    if (t == NULL) {
        return true;
    } else {
        bool bl = judgeIsBST(t->left);
        if (bl == false || prev >= t->data) {
            return false;
        }
        prev = t->data;
        bool br = judgeIsBST(t->right);
        return br;
    }
}

//7-求指定节点值在给定BST中的层次
int level(BinTree t, BinTreeElemType x) {
    BinTree p = t;
    int n = 0;
    if (p) {
        n++;
        while (p != NULL && p->data != x) {
            if (x > p->data)
                p = p->right;
            else
                p = p->left;
            n++;
        }
    }
    return (p == NULL) ? -1 : n;
}

int abs(int a) {
    if (a > 0)
        return a;
    else
        return -a;
}

//8-利用二叉树遍历的思想判断一棵树是否是平衡二叉树
void judgeAVL(BinTree t, bool* balance, int* h) {
    bool bl = false;
    bool br = false;
    int hl = 0;
    int hr = 0;
    if (t == NULL) {
        *h = 0;
        *balance = true;
    } else if (t->left == NULL && t->right == NULL) {
        *h = 1;
        *balance = 1;
    } else {
        judgeAVL(t->left, &bl, &hl);
        judgeAVL(t->right, &br, &hr);
        *h = (hl > hr ? hl : hr) + 1;
        if (abs(hl - hr) < 2) {
            *balance = bl && br;
        } else {
            *balance = false;
        }
    }
}

//9-求出给定BST中的最小和最大关键字
BinTreeElemType maxElemInBST(BinTree bt) {
    if (bt == NULL)
        return 0;
    while (bt->left)
        bt = bt->left;
    return bt->data;
}

BinTreeElemType minElemInBST(BinTree bt) {
    if (bt == NULL)
        return 0;
    while (bt->right)
        bt = bt->right;
    return bt->data;
}

//10-从大到小输出BST中所有值>=k的关键字
void printDescendingGEk(BinTree bt, int k) {
    if (bt == NULL)
        return;
    if (bt->right)
        printDescendingGEk(bt->right, k);
    if (bt->data >= k)
        printf("%d ", bt->data);
    if (bt->left)
        printDescendingGEk(bt->left, k);
}

//12-求BST中第k小的元素,其中BST的节点增设count域,保存以该节点为跟的子树上的节点个数
struct TreeNode_count {
    BinTreeElemType data;
    int count;
    struct TreeNode_count* left;
    struct TreeNode_count* right;
};
typedef struct TreeNode_count* BinTree_count;

BinTree_count findKthSamllest(BinTree_count bt, int k) {
    if (k < 1 || k > bt->count)
        return NULL;
    if (bt->left == NULL) {
        if (bt->right == NULL && k == 1) {
            return bt;
        } else {
            return findKthSamllest(bt->right, k - 1);
        }
    } else {
        if (bt->left->count == k - 1) {
            return bt;
        } else if (bt->left->count > k - 1) {
            return findKthSamllest(bt->left, k);
        } else {
            return findKthSamllest(bt->right, k - bt->left->count - 1);
        }
    }
}

测试代码

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

#include "5-5-application.c"

BinTree insertBST(BinTree root, int x) {
    if (root == NULL) {
        BinTree new = (BinTree)malloc(sizeof(struct TreeNode));
        new->data = x;
        new->left = new->right = NULL;
        return new;
    } else if (x > root->data) {
        root->right = insertBST(root->right, x);
    } else if (x < root->data) {
        root->left = insertBST(root->left, x);
    }
    return root;
}

void inOrderTraversal(BinTree t) {
    if (t) {
        inOrderTraversal(t->left);
        printf("%d ", t->data);
        inOrderTraversal(t->right);
    }
}

void test_judgeIsBST() {
    printf("\n%s\n", __func__);
    bool result;
    TreeNode n[8];
    n[0].data = -1;
    for (int i = 0; i < 8; ++i) {
        n[i].left = n[i].right = NULL;
    }
    for (int i = 1; i <= 3; ++i) {
        n[i].left = &n[2 * i];
        n[i].right = &n[2 * i + 1];
    }
    n[1].data = 34;
    n[2].data = 23;
    n[3].data = 107;
    n[4].data = 15;
    n[5].data = 28;
    n[6].data = 98;
    n[7].data = 115;
    BinTree root = n + 1;
    //inOrderTraversal(root);
    result = judgeIsBST(root);
    printf("\nresult=%d\n", result);

    prev = -1;
    n[6].data = 121;
    result = judgeIsBST(root);
    printf("\nresult=%d\n", result);

    prev = -1;
    n[3].left = NULL;
    result = judgeIsBST(root);
    printf("\nresult=%d\n", result);
}

void test_level() {
    printf("\n%s\n", __func__);
    TreeNode n[8];
    n[0].data = -1;
    for (int i = 0; i < 8; ++i) {
        n[i].left = n[i].right = NULL;
    }
    for (int i = 1; i <= 3; ++i) {
        n[i].left = &n[2 * i];
        n[i].right = &n[2 * i + 1];
    }
    n[1].data = 34;
    n[2].data = 23;
    n[3].data = 107;
    n[4].data = 15;
    n[5].data = 28;
    n[6].data = 98;
    n[7].data = 115;
    BinTree root = n + 1;

    int l;
    l = level(root, 34);
    printf("\nl=%d\n", l);
    l = level(root, 107);
    printf("\nl=%d\n", l);
    l = level(root, 98);
    printf("\nl=%d\n", l);
    l = level(root, 15);

    l = level(root, 1);
    printf("\nl=%d\n", l);
}

void test_judgeAVL() {
    printf("\n%s\n", __func__);
    TreeNode n[8];
    n[0].data = -1;
    for (int i = 0; i < 8; ++i) {
        n[i].left = n[i].right = NULL;
    }
    for (int i = 1; i <= 3; ++i) {
        n[i].left = &n[2 * i];
        n[i].right = &n[2 * i + 1];
    }
    n[1].data = 34;
    n[2].data = 23;
    n[3].data = 107;
    n[4].data = 15;
    n[5].data = 28;
    n[6].data = 98;
    n[7].data = 115;
    BinTree root = n + 1;

    bool b = false;
    int h;
    judgeAVL(root, &b, &h);
    printf("\nb=%d\n", b);
}

void test_maxElemInBST_minElemInBST() {
    printf("\n%s\n", __func__);
    TreeNode n[8];
    n[0].data = -1;
    for (int i = 0; i < 8; ++i) {
        n[i].left = n[i].right = NULL;
    }
    for (int i = 1; i <= 3; ++i) {
        n[i].left = &n[2 * i];
        n[i].right = &n[2 * i + 1];
    }
    n[1].data = 34;
    n[2].data = 23;
    n[3].data = 107;
    n[4].data = 15;
    n[5].data = 28;
    n[6].data = 98;
    n[7].data = 115;
    BinTree root = n + 1;

    int result;
    result = maxElemInBST(root);
    printf("\nmaxElem=%d\n", result);
    result = minElemInBST(root);
    printf("\nminElem=%d\n", result);
}

void test_printDescendingGEk() {
    printf("\n%s\n", __func__);
    TreeNode n[8];
    n[0].data = -1;
    for (int i = 0; i < 8; ++i) {
        n[i].left = n[i].right = NULL;
    }
    for (int i = 1; i <= 3; ++i) {
        n[i].left = &n[2 * i];
        n[i].right = &n[2 * i + 1];
    }
    n[1].data = 34;
    n[2].data = 23;
    n[3].data = 107;
    n[4].data = 15;
    n[5].data = 28;
    n[6].data = 98;
    n[7].data = 115;
    BinTree root = n + 1;
    printDescendingGEk(root, 43);
    printf("\n\n");
}

void test_findKthSamllest() {
    //不好测,算了
}

int main(int argc, char* argv[]) {
#if 0
    test_judgeIsBST();
    test_level();
    test_judgeAVL();
    test_maxElemInBST_minElemInBST();
#endif
    test_printDescendingGEk();
    return 0;
}
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
平衡二叉树是一种特殊的二叉树,它的左右子的高度差不超过1。AVL是一种自平衡的二叉搜索,它的高度始终保持在O(log n)。 下面是C语言实现平衡二叉树AVL)的代码: ``` #include <stdio.h> #include <stdlib.h> /* 定义平衡二叉树节点结构体 */ struct AVLNode { int data; // 存储的数据 int height; // 节点高度 struct AVLNode *leftChild; // 左子 struct AVLNode *rightChild; // 右子 }; /* 获取节点高度 */ int getHeight(struct AVLNode *node) { if (node == NULL) { return -1; } else { return node->height; } } /* 获取节点平衡因子 */ int getBalanceFactor(struct AVLNode *node) { if (node == NULL) { return 0; } else { return getHeight(node->leftChild) - getHeight(node->rightChild); } } /* 更新节点高度 */ void updateHeight(struct AVLNode *node) { node->height = 1 + (getHeight(node->leftChild) > getHeight(node->rightChild) ? getHeight(node->leftChild) : getHeight(node->rightChild)); } /* 右旋操作 */ struct AVLNode *rotateRight(struct AVLNode *node) { struct AVLNode *newRoot = node->leftChild; node->leftChild = newRoot->rightChild; newRoot->rightChild = node; updateHeight(node); updateHeight(newRoot); return newRoot; } /* 左旋操作 */ struct AVLNode *rotateLeft(struct AVLNode *node) { struct AVLNode *newRoot = node->rightChild; node->rightChild = newRoot->leftChild; newRoot->leftChild = node; updateHeight(node); updateHeight(newRoot); return newRoot; } /* 插入操作 */ struct AVLNode *insert(struct AVLNode *root, int data) { if (root == NULL) { root = (struct AVLNode *) malloc(sizeof(struct AVLNode)); root->data = data; root->height = 0; root->leftChild = NULL; root->rightChild = NULL; } else if (data < root->data) { root->leftChild = insert(root->leftChild, data); if (getHeight(root->leftChild) - getHeight(root->rightChild) == 2) { if (data < root->leftChild->data) { root = rotateRight(root); } else { root->leftChild = rotateLeft(root->leftChild); root = rotateRight(root); } } } else if (data > root->data) { root->rightChild = insert(root->rightChild, data); if (getHeight(root->rightChild) - getHeight(root->leftChild) == 2) { if (data > root->rightChild->data) { root = rotateLeft(root); } else { root->rightChild = rotateRight(root->rightChild); root = rotateLeft(root); } } } updateHeight(root); return root; } /* 中序遍历 */ void inOrderTraversal(struct AVLNode *root) { if (root != NULL) { inOrderTraversal(root->leftChild); printf("%d ", root->data); inOrderTraversal(root->rightChild); } } int main() { struct AVLNode *root = NULL; int data[] = {5, 2, 8, 1, 3, 6, 9}; int len = sizeof(data) / sizeof(data[0]); int i; for (i = 0; i < len; i++) { root = insert(root, data[i]); } inOrderTraversal(root); return 0; } ``` 以上代码实现了平衡二叉树的插入和中序遍历操作。在插入操作中,根据插入节点的值和当前节点的值的大小关系,不断递归向左或向右子进行插入操作,并在递归返回时更新节点高度和进行平衡操作。在平衡操作中,根据节点的平衡因子进行旋转操作,使重新平衡。在中序遍历操作中,按照左子、根节点、右子的顺序遍历中的节点,输出节点的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值