Convert Sorted List to Binary Search Tree 排序链表转二叉搜索树

将升序链表高效转换为高度平衡的二叉搜索树。利用快慢指针定位中点作为根节点,通过递归实现。适用于有序序列转换场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

给定的有序链表: [-10, -3, 0, 5, 9],

一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:

      0
     / \
   -3   9
   /   /
 -10  5

这道题关键是给定了有序的序列,所以我们只需要每次找出链表的中点作为树的根节点,然后递归调用原函数即可。其中,中点的寻找方法是快慢指针。我们需要注意边界的处理,这是递归容易忽略的问题:

其一:当head==nullptr时返回nullptr(叶子结点的子节点),当head->next==nullptr时返回new TreeNode(head->val)(叶子结点)

其二:由于我们使用了递归,一定要考虑全各种情况,当递归调用最后链表中还剩下0,1,2,3个节点时,会发生什么,当还剩0和1个节点时,上述情况已讨论过。当还剩2个节点时(比如a->b时),经过程序执行,last,slow指向a,fast指向b,这时slow会被作为中点,last会被作为除去a以前链表的尾节点,但是a已经被占用了,所以我们递归调用时一定要有这句条件判断

if (slow != head) {
     cur->left = sortedListToBST(head);
}

因为fast总是正确的,不需要判断。

以下是程序代码:

    TreeNode* sortedListToBST(ListNode* head) {
	 if (!head) {
		 return nullptr;
	 }
	 if (!head->next) {
		 return new TreeNode(head->val);
	 }
	 ListNode* fast;
	 ListNode* slow;
	 ListNode* last;
	 fast = slow = last = head;
	 while (fast->next && fast->next->next) {
		 last = slow;
		 slow = slow->next;
		 fast = fast->next->next;
	 }
	 fast = slow->next;
	 last->next = nullptr;
	 TreeNode* cur = new TreeNode(slow->val);
	 if (slow != head) {
		 cur->left = sortedListToBST(head);
	 }
	 cur->right = sortedListToBST(fast);
	 return cur;        
    }
























以下是一个简单的实现: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int value; struct node *left; struct node *right; } Node; Node *build_tree(int *preorder, int *inorder, int len) { if (len == 0) { return NULL; } int root_value = *preorder; int i; for (i = 0; i < len; i++) { if (*(inorder + i) == root_value) { break; } } if (i == len) { printf("Invalid input!\n"); return NULL; } Node *root = (Node *) malloc(sizeof(Node)); root->value = root_value; root->left = build_tree(preorder + 1, inorder, i); root->right = build_tree(preorder + 1 + i, inorder + i + 1, len - i - 1); return root; } void print_postorder(Node *root) { if (root == NULL) { return; } print_postorder(root->left); print_postorder(root->right); printf("%d ", root->value); } int is_bst_helper(Node *root, int min, int max) { if (root == NULL) { return 1; } if (root->value < min || root->value > max) { return 0; } return is_bst_helper(root->left, min, root->value - 1) && is_bst_helper(root->right, root->value + 1, max); } int is_bst(Node *root) { return is_bst_helper(root, -2147483648, 2147483647); } void get_min_max(Node *root, int *min, int *max) { if (root == NULL) { return; } if (root->value < *min) { *min = root->value; } if (root->value > *max) { *max = root->value; } get_min_max(root->left, min, max); get_min_max(root->right, min, max); } void convert_to_list_helper(Node *root, Node **prev) { if (root == NULL) { return; } convert_to_list_helper(root->left, prev); root->left = *prev; if (*prev != NULL) { (*prev)->right = root; } *prev = root; convert_to_list_helper(root->right, prev); } Node *convert_to_list(Node *root) { Node *prev = NULL; convert_to_list_helper(root, &prev); while (root != NULL && root->left != NULL) { root = root->left; } return root; } int main() { int n; printf("Enter the number of nodes: "); scanf("%d", &n); int *preorder = (int *) malloc(n * sizeof(int)); int *inorder = (int *) malloc(n * sizeof(int)); printf("Enter the preorder sequence: "); for (int i = 0; i < n; i++) { scanf("%d", preorder + i); } printf("Enter the inorder sequence: "); for (int i = 0; i < n; i++) { scanf("%d", inorder + i); } Node *root = build_tree(preorder, inorder, n); if (root != NULL) { printf("Postorder sequence: "); print_postorder(root); printf("\n"); if (is_bst(root)) { int min = 2147483647; int max = -2147483648; get_min_max(root, &min, &max); printf("Minimum value: %d\n", min); printf("Maximum value: %d\n", max); Node *list_root = convert_to_list(root); printf("Sorted list: "); while (list_root != NULL) { printf("%d ", list_root->value); list_root = list_root->right; } printf("\n"); } else { printf("The tree is not a binary search tree!\n"); } } free(preorder); free(inorder); return 0; } ``` 该程序首先要求用户输入前序和中序遍历序列,然后构建一棵二叉树,并打印其后序遍历序列。如果输入的序列无法构建一棵二叉树,则程序会输出错误提示。 接下来,程序会判断该二叉树是否是二叉搜索树。如果是,程序会输出该树的最小和最大关键字,并将该树换成一个排序的双向链表。 注意,该程序中的二叉树节点结构体包括一个整数值,以及左右子树指针。`build_tree()` 函数通过递归地构建左右子树来构建整棵二叉树。`print_postorder()` 函数通过递归地遍历左右子树来打印二叉树的后序遍历序列。 `is_bst_helper()` 函数是一个递归函数,用于判断一个二叉树是否是二叉搜索树。该函数使用 `min` 和 `max` 参数来维护当前节点值必须满足的最小和最大值。`is_bst()` 函数是一个简单的包装函数,用于调用 `is_bst_helper()` 函数。 `get_min_max()` 函数使用递归来找到二叉搜索树中的最小和最大关键字。`convert_to_list_helper()` 函数通过递归地遍历二叉树来将其换成一个排序的双向链表。`convert_to_list()` 函数是一个简单的包装函数,用于调用 `convert_to_list_helper()` 函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值