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

本文详细介绍了2022年王道数据结构第五章关于树与二叉树的C语言实现,涵盖二叉树结构、非递归遍历、树的高度计算、二叉树构建、完整性和度数等核心概念,以及实际应用如二叉搜索树判断、平衡树检查等。

概述

这是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;
}
算法:C语言实现 (第1-4部分)基础知识、数据结构、排序及搜索(原书第3) 本书是Sedgewick彻底修订和重写的C算法系列的第一本。全书分为四部分,共16。第一部分“基础知识”(第1—2)介绍基本算法分析原理。第二部分“数据结构”(第3~5)讲解算法分析中必须掌握的数据结构知识,主要包括基本数据结构、抽象数据结构、递归和。第三部分“排序”(第6~11)按节顺序分别讨论基本排序方法(如选择排序、插入排序、冒泡排序、希尔排序等)、快速排序方法、归并和归并排序方法、优先队列堆排序方法、基数排序方法以及特殊用途的排序方法,并比较了各种排序方法的性能特征。第四部分“搜索”(第12~16)在进一步讲解符号表、等抽象数据类型的基础上,重点讨论散列方法、基数搜索以及外部搜索方法。 书中提供了用C语言描述的完整算法源程序,并且配有丰富的插图和练习。作者用简洁的实现将理论和实践成功地结合了起来,这些实现均可在真实应用上测试,使得本书自问世以来备受程序员的欢迎。 本书可作为高等院校计算机相关专业算法数据结构课程的教材和补充读物,也可供自学之用。 目录 出者的话 译者序 前言 第一部分 基础知识  第1 引言   1.1 算法   1.2 典型问题——连通性   1.3 合并一查找算法   1.4 展望   1.5 主题概述  第2 算法分析的原理   2.1 实现和经验分析   2.2 算法分析   2.3 函数的增长   2.4 大O符号   2.5 基本递归方程   2.6 算法分析示例   2.7 保证、预测及局限性 第二部分 数据结构  第3 基本数据结构   3.1 构建组件   3.2 数组   3.3 链表   3.4 链表的基本处理操作   3.5 链表的内存分配   3.6 字符串   3.7 复合数据结构  第4 抽象数据类型   4.1 抽象对象和对象集   4.2 下推栈ADT   4.3 栈ADT客户示例   4.4 栈ADT的实现   4.5 创建一个新ADT   4.6 FIFO队列和广义队列   4.7 复制和索引项   4.8 一级ADT   4.9 基于应用的ADT示例   4.10 展望  第5 递归   5.1 递归算法   5.2 分治法   5.3 动态规划   5.4    5.5 的数学性质   5.6 的遍历   5.7 递归二叉树算法   5.8 图的遍历   5.9 综述 第三部分 排序  第6 基本排序方法   6.1 游戏规则   6.2 选择排序   6.3 插入排序   6.4 冒泡排序   6.5 基本排序方法的性能特征   6.6 希尔排序   6.7 对其他类型的数据进行排序   6.8 索引和指针排序   6.9 链表排序   6.10 关键字索引统计  第7 快速排序   7.1 基本算法   7.2 快速排序算法的性能特征   7.3 栈大小   7.4 小的子文件   7.5 三者取中划分   7.6 重复关键字   7.7 字符串和向量   ……  第8 归并归并排序  第9 优先队列和堆排序  第10 基数排序  第11 特殊用途的排序方法 第四部分 搜索  第12 符号表和二叉搜索  第13 平衡  第14 散列  第15 基数搜索  第16 外部搜索
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值