二叉树入门到进阶——c语言刷题合集

二叉树概念

二叉树的遍历方式

DFS(前序 中序 后序遍历)

144. 二叉树的前序遍历

递归解法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

#define MAX_NUM 100

void PreTra(int *arr, int *returnSize, struct TreeNode *node)
{
    if (node == NULL) {
        return;
    }
    arr[(*returnSize)++] = node->val;
    PreTra(arr, returnSize, node->left);
    PreTra(arr, returnSize, node->right);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
    *returnSize = 0;
    int *res = malloc(sizeof(int) * MAX_NUM);
    PreTra(res, returnSize, root);
    return res;
}

迭代解法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

#define MAX_NUM 100

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
    int top = 0;
    struct TreeNode* stack[MAX_NUM];
    stack[top++] = root;
    struct TreeNode* node;

    int *res = malloc(sizeof(int) * MAX_NUM);
    *returnSize = 0;
    while (top != 0) {
        node = stack[--top];
        if (node == NULL) {
            break;
        }
        res[(*returnSize)++] = node->val;
        if (node->right != NULL) {
            stack[top++] = node->right;
        } 
        if (node->left != NULL) {
            stack[top++] = node->left;
        }
    }

    return res;
}   

94. 二叉树的中序遍历

145. 二叉树的后序遍历

层序遍历--队列的作用

102. 二叉树的层序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */

#define MAX_LEN 2000

int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes)
{
    *returnSize = 0;
    if (root == NULL) {
        return NULL;
    }

    int **res = (int **)malloc(sizeof(int *) * MAX_LEN);
    *returnColumnSizes = (int *)malloc(sizeof(int) * MAX_LEN);

    struct TreeNode *node = root;
    struct TreeNode *list[MAX_LEN];
    int head, tail;
    head = 0, tail = 0;
    list[tail++] = node; // 第一次入队

    int lastTail, index;
    while (head != tail) {
        lastTail = tail;
        // 申请内存
        res[(*returnSize)] = malloc(sizeof(int) * (tail - head));
        (*returnColumnSizes)[(*returnSize)] = tail - head;
        index = 0;
        while (head < lastTail) {
            // 出队
            node = list[head++];
            res[(*returnSize)][index++] = node->val;
            if (node->left != NULL) {
                list[tail++] = node->left;
            }
            if (node->right != NULL) {
                list[tail++] = node->right;
            }
        }
        (*returnSize)++;
    }
    return res;
}

107. 二叉树的层序遍历 II

429. N 叉树的层序遍历

二叉搜索树

概念:

有效 二叉搜索树定义如下:

节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

98. 验证二叉搜索树

graph graphname {
a -- b -- c;
b -- d;
}

  • 思路1:利用中序遍历,将二叉树转换为数组,然后判断数组是否有序

  • 思路2:直接在递归过程中,有两个指针模拟左(pre)->中(cur)->右,左->中(pre)->右(cur)

    • 陷阱:不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了,要比较的是左子树所有节点小于中间节点,右子树所有节点大于中间节点
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 
bool isOk(struct TreeNode *cur, struct TreeNode **pre)
{
    if (cur == NULL) return true; // 先沉底

    bool left = isOk(cur->left, pre);
    if (*pre != NULL && (*pre)->val >= cur->val) {
        return false;
    }
    // if (*pre != NULL) printf("cur=%d, pre=%d\n", cur->val, (*pre)->val);
    *pre = cur;
    bool right = isOk(cur->right, pre);

    return left && right;
}

bool isValidBST(struct TreeNode* root)
{
    struct TreeNode *pre = NULL;
    return isOk(root, &pre);
}
  • 思路3:迭代法,用栈模拟递归压栈和弹栈的过程
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define MAX_NUM 10000

bool isValidBST(struct TreeNode* root)
{
    int top = 0;
    struct TreeNode *stack[MAX_NUM];
    struct TreeNode *cur = root;
    struct TreeNode *pre = NULL;

    // 用栈模拟 递归压栈和弹栈的过程
    while (cur != NULL || top != 0) {
        if (cur != NULL) {
            stack[top++] = cur; 
            cur = cur->left; // 左
        } else {
            cur = stack[--top];
            if (pre != NULL && pre->val >= cur->val) return false;
            pre = cur;

            cur = cur->right;
        }
    }
    return true;
}

700. 二叉搜索树中的搜索

  • 递归
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* searchBST(struct TreeNode* root, int val)
{
    if (root == NULL) return NULL;

    if (root->val == val) {
        return root;
    } else if (root->val > val) {
        return searchBST(root->left, val);
    } else {
        return searchBST(root->right, val);
    }

    return NULL;
}
  • 迭代法
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* searchBST(struct TreeNode* root, int val)
{
    while (root != NULL) {
        if (root->val == val) {
            return root;
        } else if (root->val > val) {
            root = root->left;
        } else {
            root = root->right;
        }
    }
    return NULL;
}

501. 二叉搜索树中的众数

  • 中序遍历1次搞定,不适用额外的空间:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

int g_preVal, g_count, g_maxCount;
int g_resSize;
int *g_res;

void Update(int curVal)
{
    if (curVal == g_preVal) {
        g_count++;
    } else {
        g_preVal = curVal;
        g_count = 1;
    }

    if (g_count == g_maxCount) {
        g_res[g_resSize++] = curVal;
    }
    if (g_count > g_maxCount) {
        g_maxCount = g_count;
        g_resSize = 0;
        g_res[g_resSize++] = curVal;
    }
}

/* 中序遍历 */
void MidTravle(struct TreeNode *node)
{   
    if (node == NULL) return;
    MidTravle(node->left);
    Update(node->val);
    MidTravle(node->right);
}

int* findMode(struct TreeNode* root, int* returnSize)
{
    g_count = 0, g_maxCount = 0, g_resSize = 0;
    g_preVal = root->val;
    g_res = malloc(sizeof(int) * 10001);

    MidTravle(root);
    *returnSize = g_resSize;
    return g_res;
}
  • 使用hash表记录出现次数,使用了额外空间,并且还需要排序
struct HashTable {
    int num;
    int count;
    UT_hash_handle hh;
};

struct HashTable *g_hash;
int g_count = 0;

struct HashTable *FindeNode(int num)
{
    struct HashTable *tmp = NULL;
    HASH_FIND_INT(g_hash, &num, tmp);
    return tmp;
}

void AddNode(int num)
{
    struct HashTable *tmp = FindeNode(num);
    if (tmp == NULL) {
        g_count++;
        tmp = malloc(sizeof(struct HashTable));
        tmp->num = num;
        tmp->count = 1;
        HASH_ADD_INT(g_hash, num, tmp);
    } else {
        tmp->count++;
    }
}

void Func(struct TreeNode *node)
{
    if (node == NULL) return;
    AddNode(node->val);
    Func(node->left);
    Func(node->right);
}

int HashSort(struct HashTable *a, struct HashTable *b)
{
    return b->count - a->count;
}

int* findMode(struct TreeNode* root, int* returnSize)
{
    // 1、遍历整棵树
    // 2、记录每个数字出现的次数
    // 3、返回出现次数最高的数
    g_hash = NULL;
    
    Func(root);
    HASH_SORT(g_hash, HashSort);
    
    int n = g_hash->count;

    int *res = malloc(sizeof(int) * g_count);
    *returnSize = 0;

    struct HashTable *cur, *tmp;
    HASH_ITER(hh, g_hash, cur, tmp) {
        if (cur->count == n) {
            res[(*returnSize)++] = cur->num;
        }
        HASH_DEL(g_hash, cur);
        free(cur);
    }
    return res;
}

108. 将有序数组转换为二叉搜索树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode *Func(int *arr, int len)
{
    if (len == 0) return;

    int mid = len / 2;
    struct TreeNode *node = malloc(sizeof(struct TreeNode));
    node->val = arr[mid];

    node->left = Func(arr, mid);
    node->right = Func(arr + mid + 1, len - mid - 1);

    return node;
}

struct TreeNode* sortedArrayToBST(int* nums, int numsSize)
{
    if (numsSize == 0) return NULL;

    struct TreeNode *root = Func(nums, numsSize);
    return root;
}

二叉树剪枝

450.删除二叉搜索树中的节点

  • 涉及到树结构的调整,较为复杂
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


struct TreeNode* deleteNode(struct TreeNode* root, int key)
{
    if (root == NULL) return NULL;

    if (root->val == key) {
        if (root->left == NULL && root->right == NULL) {
            free(root);
            return NULL;
        }
        if (root->left != NULL && root->right == NULL) {
            struct TreeNode *node = root->left;
            free(root);
            return node;
        }
        if (root->left == NULL && root->right != NULL) {
            struct TreeNode *node = root->right;
            free(root);
            return node;
        }
        // 左右孩子都非空
        struct TreeNode *left = root->left; // 左
        struct TreeNode *right = root->right; // 左
        struct TreeNode *node = right; // 左
        free(root);
        while (right->left != NULL) {
            right = right->left;
        }
        // 挂上
        right->left = left;
        return node;
    }

    if (root->val > key) {
        root->left = deleteNode(root->left, key);
    }
    if (root->val < key) {
        root->right = deleteNode(root->right, key);
    }

    return root;
}

回溯思想

236. 二叉树的最近公共祖先

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

 /*
 * 1.前序遍历
 * 2.左子树和右子树每颗树都完整的遍历1遍
 * 3.回溯,利用左子树和右子树的返回值,来判断最近公共祖先
 */
struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) 
{
    if (root == p || root == q || root == NULL) return root;
    
    struct TreeNode *left = lowestCommonAncestor(root->left, p, q);
    struct TreeNode *right = lowestCommonAncestor(root->right, p, q);

    if (left != NULL && right != NULL) return root;
    if (left == NULL && right != NULL) return right;
    return left;
}

235. 二叉搜索树的最近公共祖先

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) 
{
    if (root == NULL || root == q || root == p) return root;

    int val = root->val;
    if (p->val < val && q->val < val) {
        return lowestCommonAncestor(root->left, p, q);
    } else if (p->val > val && q->val >val) {
        return lowestCommonAncestor(root->right, p, q);
    } else {
        return root;    
    }
}

二叉树中的插入操作

701.二叉搜索树中的插入操作

  • 递归解法
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


struct TreeNode* insertIntoBST(struct TreeNode* root, int val)
{
    if (root == NULL) {
        struct TreeNode *node = malloc(sizeof(struct TreeNode));
        node->val = val;
        node->left = NULL;
        node->right = NULL;
        root = node;
        return root;
    }

    if (root->val > val) {
        root->left = insertIntoBST(root->left, val);
    }
    if (root->val < val) {
        root->right = insertIntoBST(root->right, val);
    }

    return root;
}
  • 迭代解法
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


struct TreeNode* insertIntoBST(struct TreeNode* root, int val)
{
    struct TreeNode *node = root;
    struct TreeNode *add = malloc(sizeof(struct TreeNode));
    add->val = val;
    add->left = NULL;
    add->right = NULL;
    if (node == NULL) return add;

    while (node != NULL) {
        if (node->val > val && node->left == NULL) {
            node->left = add;
            break;
        }
        if (node->val < val && node->right == NULL) {
            node->right = add;
            break;
        }

        if (node->left != NULL && val < node->val) {
            node = node->left;
        }
        if (node->right != NULL && val > node->val) {
            node = node->right;
        }
    }
    return root;
}

构建二叉树

105. 从前序与中序遍历序列构造二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize)
{
    if (preorderSize == 0) return NULL;

    int leftSize, rightSize;
    struct TreeNode *node = malloc(sizeof(struct TreeNode));
    node->val = preorder[0];
    for (int i = 0; i < inorderSize; i++) {
        if (node->val == inorder[i]) {
            leftSize = i;
            break;
        }
    }
    rightSize = inorderSize - leftSize - 1;
    node->left = buildTree(preorder + 1, leftSize, inorder, leftSize);
    node->right = buildTree(preorder + 1 + leftSize, rightSize, inorder + leftSize + 1, rightSize);

    return node;
}

106. 从中序与后序遍历序列构造二叉树

108.将有序数组转换为二叉搜索树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

struct TreeNode *Func(int *arr, int len)
{
    if (len == 0) return;

    int mid = len / 2;
    struct TreeNode *node = malloc(sizeof(struct TreeNode));
    node->val = arr[mid];

    node->left = Func(arr, mid);
    node->right = Func(arr + mid + 1, len - mid - 1);

    return node;
}

struct TreeNode* sortedArrayToBST(int* nums, int numsSize)
{
    if (numsSize == 0) return NULL;

    struct TreeNode *root = Func(nums, numsSize);
    return root;
}

完全二叉树

  • 参考数据结构
  • 完全二叉树定义:
    完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

验证完全二叉树

222. 完全二叉树的节点个数

剑指 Offer II 043. 往完全二叉树添加节点

二叉树的后继节点

  • 举个例子
    image
  1. x有右树的时候:后继节点为其右树最左边的节点
  2. x没有右树的时候:往其左树找,当找到节点为其父节点的左孩子时,则这个父节点为x的后继节点
    image
  • 后继节点定义:中序遍历中,节点node的后一个节点叫做node的后继节点
  • 前驱节点定义:中序遍历中,节点node的前一个节点叫做node的前驱节点

285. 二叉搜索树中的中序后继(Plus)

image

#define MAX_LEN 10000

struct TreeNode* inorderSuccessor(struct TreeNode* root, struct TreeNode* p) 
{
    int top = 0;
    struct TreeNode *stack[MAX_LEN];
    
    struct TreeNode *pre = NULL;
    struct TreeNode *cur = root;

    while (cur != NULL || top != 0) {
        if (cur != NULL) {
            stack[top++] = cur;
            cur = cur->left; 
        } else {
            cur = stack[--top];
            // printf("%d\n", cur->val);
            if (pre == p) {
                return cur;
            }
            pre = cur;
            cur = cur->right;
        }
    }

    return NULL;
}

510. 二叉搜索树中的中序后继 II(Plus)

image
image
image

/*
// Definition for a Node.
struct Node {
    int val;
    struct Node* left;
    struct Node* right;
    struct Node* parent;
};
*/

struct Node* ProcRight(struct Node *node)
{
    while (node != NULL) {
        if (node->left == NULL) {
            return node;
        }
        node = node->left;
    }
    return node;
}

struct Node* ProcNoRight(struct Node *node)
{
    struct Node *p = NULL;
    while (node != NULL) {
        p = node->parent;
        if (p != NULL && p->left == node) {
            return p;
        }
        node = p;
    }
    // 囊括了node为整棵二叉树最底层最右侧节点的情况,返回NULL
    return node;
}

struct Node* inorderSuccessor(struct Node* node) 
{
    if (node == NULL) {
        return node;
    }
	
    // 根据中序遍历,找node的后继节点有2种情况
    // 1. node有右子树,则后继节点为右子树最左的节点
    // 2. node无右子树,则向上找父节点,当这个父节点是再上一层节点p的左节点时,这个p为后继节点


    // 1
    if (node->right != NULL) {
        return ProcRight(node->right);
    }

    // 2
    return ProcNoRight(node);
}

2二叉树的序列化与反序列化

297. 二叉树的序列化与反序列化

posted @ 2022-12-06 14:30  胖白白  阅读(73)  评论(0编辑  收藏  举报