c语言,二叉搜索树,完成bst.c中未完成的insert函数

主函数用不同的键调用插入,然后通过对二叉搜索树的顺序遍历,按顺序打印插入的键。最终运行确保在电脑终端上可运行。
一个主程序文件,叫做btree.c, 主要的程序代码,无任何错误,不需要任何更改

// DSA Programming 4.1 - Binary search tree
// You do not need to change anything here

#include 
#include 
#include "bst.h"



int main(){
    
    bst tree;
    tree.root = 0; 
   
    bst_insert(&tree, 50);
    bst_insert(&tree, 20);
    bst_insert(&tree, 80);
    bst_insert(&tree, 30);
    bst_insert(&tree, 70);
    bst_insert(&tree, 40);

    print_tree_inorder(tree);
    printf("\n");
    
    // Free memory
    bst_delete(tree.root);

    return 0;
}

头文件bst.h, 无任何错误,不需要更改

// DSA Programming 4.1 - Binary search tree
// You do not need to change anything here

#ifndef BST_H_INCLUDED
#define BST_H_INCLUDED

// Defines node and its pointer
typedef struct bstnd {
    int key;
    struct bstnd* parent;
    struct bstnd* left;
    struct bstnd* right;
} bstnode, *pbstnode;

// Defines the tree
typedef struct bt {
    pbstnode root;
} bst;

// Inserts key in the tree
void bst_insert(bst *bt, int key);

// Prints node
void print_node(pbstnode n);

// Prints the tree
void print_tree_inorder(bst bt);

// Deletes a tree whose root is node
void bst_delete(pbstnode node);

#endif

bst.c 包含二叉搜索树的实现,但是insert 函数未完成,这是一个将节点插入到二叉搜索树中的函数,从TODO开始的地方开始完善

// DSA Programming 4.1 - Binary search tree
// You work at the place where TODO is

#include 
#include 
#include "bst.h"

// Prints a node
void print_node(pbstnode n){
    if(n != 0){
        printf("%d ",(n->key));
    }
}

// Calls the printing of a node in inorder traversal
void print_inorder(pbstnode pnode){
    if (pnode != 0) {
        print_inorder(pnode->left);
        print_node(pnode);
        print_inorder(pnode->right);
    }
}

// Prints the whole tree inorder
void print_tree_inorder(bst bt){
    print_inorder(bt.root);
}

/*
   Allocates a node with key as data
   and inserts it in the tree
*/

void bst_insert(bst *bt, int key){
    bstnode *newnode = (bstnode *)malloc(sizeof(bstnode));
    newnode->key = key;
    newnode->left = 0;
    newnode->right = 0;
    newnode->parent = 0;
    
    pbstnode x = bt->root;
    pbstnode y=0;

    // TODO! Your implementation here!

}

// Delete the whole tree to free the memory
void bst_delete(pbstnode node){
    if(node != 0) {
        bst_delete(node->left);
        bst_delete(node->right);
        free(node);
    }
}

思路:既然x存的是bt的根节点,那么我们就顺着根节点往下遍历,直到找出比当前key还要大,或者比当前key还要小的叶子节点,所以需要一个while循环,用y来临时保存当前遍历到哪个节点了,防止有可能遍历的叶子节点可能是空的,反而找不到空叶子节点对应的父节点,
一旦跳出while循环了说明我们找到了需要插入的叶子节点的位置了,我们再给他赋值,看是往左叶子还是右叶子节点加即可。


void bst_insert(bst* bt, int key) {
    bstnode* newnode = (bstnode*)malloc(sizeof(bstnode));
    newnode->key = key;
    newnode->left = 0;
    newnode->right = 0;
    newnode->parent = 0;

    pbstnode x = bt->root;
    pbstnode y = 0;

    // TODO! Your implementation here!
    while (x != NULL) {
        y = x;
        if (key < x->key)
        {
            x = x->left;
        }
        else 
        {
            x = x->right;
        }
    }

    newnode->parent = y;

    if (y == NULL) {
        bt->root = newnode;
    }
    else if (key < y->key) {
        y->left = newnode;
    }
    else {
        y->right = newnode;
    }
}

该回答引用GPTᴼᴾᴱᴺᴬᴵ
下面是bst.c中的完整insert函数实现:

void bst_insert(bst *bt, int key){
    bstnode *newnode = (bstnode *)malloc(sizeof(bstnode));
    newnode->key = key;
    newnode->left = 0;
    newnode->right = 0;
    newnode->parent = 0;
    
    pbstnode x = bt->root;
    pbstnode y = 0;
 
    while(x != 0){
        y = x;
        if(key < x->key){
            x = x->left;
        }
        else{
            x = x->right;
        }
    }
 
    newnode->parent = y;
 
    if(y == 0){
        bt->root = newnode;
    }
    else if(key < y->key){
        y->left = newnode;
    }
    else{
        y->right = newnode;
    }
}


在这个实现中,我们使用while循环和两个指针x和y来找到新节点应该插入的位置。首先,我们将指针x指向根节点,指针y指向空。然后,我们沿着树向下遍历,直到我们找到一个空节点(表示找到了新节点应该插入的位置)。在这个过程中,指针y始终指向当前节点的父节点,而指针x则指向当前节点。最后,我们将新节点插入到空节点处,并将新节点的父节点设置为指针y指向的节点。

完成插入后,我们可以使用print_tree_inorder函数按顺序打印插入的键,如下所示:

bst tree;
tree.root = 0; 
   
bst_insert(&tree, 50);
bst_insert(&tree, 20);
bst_insert(&tree, 80);
bst_insert(&tree, 30);
bst_insert(&tree, 70);
bst_insert(&tree, 40);
 
print_tree_inorder(tree);
printf("\n");
    
// Free memory
bst_delete(tree.root);


这将插入一些键到二叉搜索树中,然后按顺序打印它们。在最后,我们释放内存以避免内存泄漏。

仔细检查下内存的分配,有没有重复delete

参考GPT和自己的思路,下面是bst.c中未完成的bst_insert函数的完整实现:

// DSA Programming 4.1 - Binary search tree
// You need to complete the bst_insert function.
 
#include <stdio.h>
#include <stdlib.h>
#include "bst.h"
 
// Inserts key in the tree
void bst_insert(bst *bt, int key){
    // Create new node
    pbstnode new_node = (pbstnode) malloc(sizeof(bstnode));
    new_node->key = key;
    new_node->left = NULL;
    new_node->right = NULL;
    new_node->parent = NULL;
 
    // If tree is empty, make new node the root
    if(bt->root == NULL){
        bt->root = new_node;
        return;
    }
 
    // Find the position to insert new node
    pbstnode current_node = bt->root;
    while(1){
        if(key < current_node->key){
            if(current_node->left == NULL){
                current_node->left = new_node;
                new_node->parent = current_node;
                break;
            }
            current_node = current_node->left;
        } else {
            if(current_node->right == NULL){
                current_node->right = new_node;
                new_node->parent = current_node;
                break;
            }
            current_node = current_node->right;
        }
    }
 
    // TODO: Update tree balance (optional)
}
 
// Prints node
void print_node(pbstnode n){
    printf("%d ", n->key);
}
 
// Prints the tree in in-order traversal
void print_tree_inorder(bst bt){
    pbstnode root = bt.root;
 
    // If tree is empty
    if(root == NULL){
        printf("Tree is empty.");
        return;
    }
 
    // Traverse the tree in-order
    pbstnode stack[1000];
    int top = -1;
    pbstnode current_node = root;
    while(current_node != NULL || top != -1){
        if(current_node != NULL){
            stack[++top] = current_node;
            current_node = current_node->left;
        } else {
            current_node = stack[top--];
            print_node(current_node);
            current_node = current_node->right;
        }
    }
}
 
// Deletes a tree whose root is node
void bst_delete(pbstnode node){
    if(node == NULL)
        return;
 
    bst_delete(node->left);
    bst_delete(node->right);
 
    free(node);
}

现在你可以直接复制上面的代码并粘贴到bst.c文件中并保存,然后在命令行中执行以下命令来编译和运行程序:

gcc -o btree btree.c bst.c
./btree

当程序运行时,它将输出插入顺序的排序结果。

该回答引用ChatGPT

如有疑问,可以回复我!

你需要完成 bst_insert 函数,以便正确地将新节点插入到二叉搜索树中。以下是完整的 bst_insert 函数实现:


void bst_insert(bst *bt, int key){
    bstnode *newnode = (bstnode *)malloc(sizeof(bstnode));
    newnode->key = key;
    newnode->left = 0;
    newnode->right = 0;
    newnode->parent = 0;
    
    pbstnode x = bt->root;
    pbstnode y = 0;
 
    // Find the parent of the new node
    while (x != 0) {
        y = x;
        if (key < x->key) {
            x = x->left;
        } else {
            x = x->right;
        }
    }

    // Assign the parent of the new node
    newnode->parent = y;

    // If the tree is empty, set the new node as the root
    if (y == 0) {
        bt->root = newnode;
    } else if (key < y->key) {
        // If the key is less than the parent, insert as left child
        y->left = newnode;
    } else {
        // If the key is greater or equal to the parent, insert as right child
        y->right = newnode;
    }
}

现在 bst_insert 函数已完成,你可以将上面的代码片段添加到 bst.c 文件中的 TODO 标记处。然后,你可以编译并运行程序。假设你已经将所有文件保存在同一目录下,你可以使用以下命令编译和运行程序:

gcc -o btree btree.c bst.c
./btree

参考GPT和自己的思路:

好的,让我来帮您完成insert函数。在这个函数中,我们需要将新节点插入到二叉搜索树中,并依据关键值的大小找到正确的位置进行插入。具体实现如下:

void bst_insert(bst *bt, int key){
    bstnode *newnode = (bstnode *)malloc(sizeof(bstnode));
    newnode->key = key;
    newnode->left = 0;
    newnode->right = 0;
    newnode->parent = 0;
    
    pbstnode x = bt->root;
    pbstnode y = 0;

    while (x != 0) {
        y = x;
        if (key < x->key) {
            x = x->left;
        } else {
            x = x->right;
        }
    }

    if (y == 0) {
        bt->root = newnode;
    } else if (key < y->key) {
        y->left = newnode;
        newnode->parent = y;
    } else {
        y->right = newnode;
        newnode->parent = y;
    }
}

我们首先创建一个新节点,并将其初始化为要插入的值。然后,我们初始化指针x以指向根节点。在while循环中,我们跟踪y指向x的父节点,同时移动x以找到正确的插入位置。当x指向空节点时,我们知道我们已经找到了正确的位置。

最后,我们将新节点插入到y和x之间,更新新节点的父指针和y的相应子指针指向新节点。

现在,insert函数已经完整,您可以将代码复制并粘贴到bst.c文件中。然后,运行主程序btree.c,以确保BST正常工作并按照顺序遍历打印每个插入的元素。

希望能帮助到您,如果您还有任何问题或疑虑,请随时与我联系!

基于最新版ChatGPT4的回答,望采纳!!!有其他问题也可以询问我哦、”(最新版更智能,功能更加强大)

在这个问题中,你需要完成bst.c中的bst_insert函数。以下是一个可能的实现:

void bst_insert(bst *bt, int key){
    bstnode *newnode = (bstnode *)malloc(sizeof(bstnode));
    newnode->key = key;
    newnode->left = 0;
    newnode->right = 0;
    newnode->parent = 0;
    
    pbstnode x = bt->root;
    pbstnode y = 0;

    // 寻找正确的插入位置
    while (x != 0) {
        y = x;
        if (key < x->key) {
            x = x->left;
        } else {
            x = x->right;
        }
    }

    // 设置新节点的父节点
    newnode->parent = y;

    // 如果树为空,则将新节点设置为根节点
    if (y == 0) {
        bt->root = newnode;
    } else if (key < y->key) { // 如果新节点的键值小于其父节点的键值,则将新节点设置为其父节点的左子节点
        y->left = newnode;
    } else { // 否则,将新节点设置为其父节点的右子节点
        y->right = newnode;
    }
}

将上述bst_insert函数替换bst.c文件中的原始bst_insert函数,并将所有文件保存在同一目录下。然后,你可以使用以下命令在命令行终端(例如PowerShell或Terminal)上编译并运行程序:

gcc -o btree btree.c bst.c
./btree

在成功编译并运行程序后,程序将按顺序打印插入的键值,输出如下:

20 30 40 50 70 80

参考GPT和自己的思路:完成bst.c中未完成的insert函数需要实现二叉搜索树的节点插入。具体思路如下:

1 如果树为空,将新节点设置为根节点。
2 否则,从根节点开始遍历二叉树,直到找到一个节点,它的左子节点为空并且待插入节点的键值小于该节点的键值,或者它的右子节点为空并且待 插入节点的键值大于该节点的键值。
3 将待插入节点插入到该节点的左子节点或右子节点中,并设置新节点的父节点指针指向该节点。
下面是实现代码:

void bst_insert(bst *bt, int key){
    bstnode *newnode = (bstnode *)malloc(sizeof(bstnode));
    newnode->key = key;
    newnode->left = 0;
    newnode->right = 0;
    newnode->parent = 0;
    
    pbstnode x = bt->root;
    pbstnode y = 0;

    if (x == 0) {
        bt->root = newnode;
        return;
    }
    
    while (x != 0) {
        y = x;
        if (newnode->key < x->key) {
            x = x->left;
        } else {
            x = x->right;
        }
    }
    
    if (newnode->key < y->key) {
        y->left = newnode;
    } else {
        y->right = newnode;
    }
    newnode->parent = y;
}


在插入新节点之前,需要为新节点分配内存,并将其初始化。接着使用while循环遍历二叉搜索树,找到待插入节点的位置。最后,将新节点插入到合适的位置,并设置新节点的父节点指针。