二叉搜索树插入节点遇Segmentation Fault及节点指针概念困惑求助
咱们先把赋值和分配的概念掰扯明白,再一步步揪出你代码里的段错误根源——这俩问题其实是绑定在一起的!
一、先搞懂赋值(Assignment) vs 分配(Allocation)
- 分配(Allocation):是从堆内存里申请一块全新的空间,用来存放你的
Node对象,比如你写的Node* nnode = new Node(data);就是干这个的。这时候nnode指向的是一块实实在在有内存的Node实例,不是空的。 - 赋值(Assignment):只是把一个指针里存的内存地址复制给另一个指针,比如
curr = node;,这时候curr和node指向的是同一个东西——如果node是NULL(没指向任何内存),那curr也会是NULL,这时候你去碰curr->data这种操作,就相当于去访问一个不存在的地址,直接触发段错误。
二、你的代码为啥会Segmentation Fault?
核心问题是while循环里的逻辑完全写反了!看这段关键代码:
while(1){ if(curr){ node=nnode; break; } else{ if(curr->data <x){ // ... 访问curr的左右子节点 } } }
- 当
curr不为NULL的时候(也就是当前有节点可以遍历),你直接把node换成新节点,然后break——这相当于把整个树直接替换成新节点,完全不是插入逻辑! - 当
curr为NULL的时候(比如空树的初始调用),你进入else分支,然后直接访问curr->data——这时候curr是NULL指针,解引用NULL指针是C++里的未定义行为,直接触发段错误!
另外还有俩小坑:
- 你注释掉的
nnode=Node(data);是错的:Node(data)是个临时对象,赋值给指针后,临时对象会立刻销毁,nnode就变成了野指针,访问它也会炸。 int x=data;完全没必要,直接用data就行,多此一举。
三、修正后的插入代码
咱们把逻辑掰正:插入的核心是遍历到合适的空位置,把新节点挂上去,空树的话直接返回新节点当根:
Node* insert(Node* node, int data) { // 如果是空树,直接返回新节点作为根 if (node == NULL) { return new Node(data); } Node* curr = node; while (true) { if (data < curr->data) { // 要插左子树 if (curr->left == NULL) { curr->left = new Node(data); break; } else { curr = curr->left; } } else if (data > curr->data) { // 要插右子树 if (curr->right == NULL) { curr->right = new Node(data); break; } else { curr = curr->right; } } else { // 遇到重复值,BST一般不允许重复,直接跳过插入 break; } } // 返回原根节点(除非是空树,否则根不变) return node; }
解释下修正点:
- 先判断空树,直接返回新节点,避免后续遍历NULL指针。
- 遍历逻辑:当当前节点的左/右子节点为空时,把新节点挂上去;否则继续往下遍历。
- 处理了重复值的情况(BST通常不允许重复,这里直接跳过插入)。
- 没有乱改根节点
node,只有空树的时候才返回新节点当根。
最后再总结下什么时候只需赋值不用分配
当你只是想让一个指针指向已经存在的对象/节点的时候,只用赋值就行,比如:
// curr已经指向一个存在的节点,现在让temp也指向它 Node* temp = curr;
而当你需要创建一个全新的节点的时候,才需要用new分配内存,然后把分配得到的指针赋值给某个变量或者子节点指针。
内容的提问来源于stack exchange,提问作者mn-gt
相关产品推荐
相关产品推荐

