算法习题1:二叉树实现增删改查

现在从基本功开始练起,好久没写二叉树,擦擦擦

这里我实现了二叉树创建以及删除,搜索,基本就是最主要的功能了,至于插入,就是创建的一部分,修改则是查找的结果。。

说下二叉树:一般我们都定义成左子树小右子树大,所以遍历的时候我们就遵从先左,然后自己,再右子树,利用递归的思想,也就是
 printBSTree(left);
printf("%d   ",p->value);
printBSTree(right);
这就是我们printBSTree()的主体了。
当然结构体定义就是
 struct BSTree{
int value;
BSTree* bsLeft;
BSTree* bsRight;
};


插入这个过程只需要遵守小的往左遍历,大的往右遍历,直至null,然后插入!

删除是二叉树里最复杂的,所以这里重点讲下,

二叉树实现增删改查 二叉树实现增删改查
          图一                             图二

一般最容易理解就是我们先分类讨论:(假设找到了所需删除点)
(1)如果所找点是叶子(例如10),那么简单,先使得父亲节点的左(右)子树(这里恰好是左子树,如果删除的是70那就是右子树,千万别因为画图而写错误代码)为NULL,然后delete p;(p就是指向10这个节点指针)
(2)如果所找节点不是叶子节点,而是同时有左子树和右子树,例如图二50这个节点,我们知道,应该找个值来代替这个节点,如果只是简简单单删去,那他们的孩儿们怎么办啊?代替,当然找一个最接近它的值,我们这里采用比50大一点点的数,当然就是50右子树的左子树的左子树的左子树。。。这个最左的就是最接近的啦,我们这里需要把50的父节点(100)指向这个新的代替节点(这里是60),然后让60的左子树指向10,60的右子树则指向70,那60原来的右子树呢?给70左子树就好了,这里有点绕,但是唯一目标就是,让60代替50,要给60和50的后代们找好后爹后妈,同时给她们的父母找好养子,但这里你考虑下,如果我们删除的是图一的50呢?你发现养子和后爹后妈是同一个节点的时候要独立考虑。
当然这里我们也可用50小一点点的数来代替。。
(3)如果只有左子树,没有右子树:例如图二70,简单,50接上60就ok啦
(4)如果只有右子树,没有左子树:例如图二60,一种方法是同上,70接上65就可以了,但是你想想,这种情况我们不是也可以按照(2)做法,把60大一点点的来代替,那就是60右子树的左子树左子树。。。。所以我们可以把这种情况归纳到(2)

Note:如果删除点是头节点呢????怎么办,这种情况应该分别注意下就好了
当然这里代码不是最优的,只是方便理解,后续有时间发上优化点好代码

//============================================================================
// Name         : BSTree_2.cpp
// Author       : YLF
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================


#include <stdio.h>
#include <iostream>

using namespace std;
//*************************
struct BSTree{
int value;
BSTree* bsLeft;
BSTree* bsRight;
};
//*************************
void printBSTree(BSTree* p);
BSTree* deleteNode(BSTree* p, int value);

int main()
{
int inputNum = 0;
//head pointer is fixed
//p pointer is scanning
BSTree* head = NULL;
BSTree* p = NULL;

//input -1 ends input
//scanf("%d",&inputNum);
cin>>inputNum;
while(inputNum!=-1){
BSTree* temp = new BSTree();
temp->value = inputNum;
temp->bsLeft = NULL;
temp->bsRight = NULL;

if(head == NULL){
head = temp;
}else{
p = head;
while(true){
if(temp->value <p->value){
if(p->bsLeft == NULL){
p->bsLeft = temp;
break;
}
p = p->bsLeft;
}
if(temp->value >=p->value){
if(p->bsRight == NULL){
p->bsRight = temp;
break;
}
p = p->bsRight;
}
}

}

cin>>inputNum;
//scanf("%d",&inputNum);
}

//read the BSTree
printBSTree(head);
cout<<"input to delete:";
cin>>inputNum;
while(inputNum!=-1){
head = deleteNode(head,inputNum);
if(head == NULL){
cout<<"binary tree isnull!!";
break;
}
printBSTree(head);
cout<<"input to delete:";
cin>>inputNum;
}
return 0;
}

void printBSTree(BSTree* p)
{
if(p == NULL)
return;
BSTree* left = p->bsLeft;
BSTree* right = p->bsRight;

printBSTree(left);
printf("%d   ",p->value);
printBSTree(right);
return;
}


BSTree* deleteNode(BSTree* head, int value)
{
//循环遍历找到该值
BSTree* parent = head;
BSTree* p = head;
while(p != NULL){
if(value < p->value ){
parent = p;
p = p->bsLeft;
}
else if(value > p->value){
parent = p;
p = p->bsRight;
}
else
break;
}
if(p == NULL){
cout<<"notfind!!"<<endl;
}

//如果都为空
if(p->bsRight==NULL&&p->bsLeft==NULL){
if(p==head){
delete p;
return NULL;
}
if(parent->bsLeft == p)
parent->bsLeft = NULL;
else if(parent->bsRight == p)
parent->bsRight = NULL;
delete p;
}
//如果有右子树
if(p->bsRight!=NULL){
BSTree* temp = p->bsRight;
BSTree* tempParent = p->bsRight;

while(temp->bsLeft!=NULL){
tempParent = temp;
temp = temp->bsLeft;
}

if(parent->bsLeft == p)
parent->bsLeft = temp;
else if(parent->bsRight == p)
parent->bsRight = temp;

if(temp!=tempParent){
tempParent->bsLeft =temp->bsRight;
temp->bsLeft = p->bsLeft;
temp->bsRight =p->bsRight;
}else{
temp->bsLeft = p->bsLeft;
}

if(head == p){
delete p;
return temp;
}

delete p;
}

//如果没有右子树
if(p->bsLeft!=NULL&&p->bsRight==NULL){
if(parent->bsLeft == p)
parent->bsLeft =p->bsLeft;
else if(parent->bsRight == p)
parent->bsRight =p->bsLeft;
if(p == head){
BSTree* temp = p->bsLeft;
delete p;
return temp;
}
delete p;
}

return head;
}


BSTree* searchNode(BSTree* head, int value, intisParent)
{
BSTree* parent = head;
BSTree* p = head;
while(p != NULL){
if(value < p->value ){
parent = p;
p = p->bsLeft;
}
else if(value > p->value){
parent = p;
p = p->bsRight;
}
else{
if(isParent == 0)
return p;
else
return parent;
}
}
return head;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是二叉树增删改查的C语言代码示例。 首先,我们需要定义二叉树的结构体: ```c struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; ``` 接下来,我们分别实现二叉树的增、删、改、查操作: 1. 增加节点 ```c struct TreeNode* insertNode(struct TreeNode* root, int val) { if (!root) { struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode)); node->val = val; node->left = NULL; node->right = NULL; return node; } if (val < root->val) { root->left = insertNode(root->left, val); } else if (val > root->val) { root->right = insertNode(root->right, val); } return root; } ``` 2. 删除节点 ```c struct TreeNode* deleteNode(struct TreeNode* root, int key) { if (!root) { return NULL; } if (root->val == key) { if (!root->left) { struct TreeNode* tmp = root->right; free(root); return tmp; } else if (!root->right) { struct TreeNode* tmp = root->left; free(root); return tmp; } else { struct TreeNode* p = root->right; while (p->left) { p = p->left; } root->val = p->val; root->right = deleteNode(root->right, p->val); } } else if (root->val > key) { root->left = deleteNode(root->left, key); } else { root->right = deleteNode(root->right, key); } return root; } ``` 3. 修改节点 ```c struct TreeNode* modifyNode(struct TreeNode* root, int oldVal, int newVal) { root = deleteNode(root, oldVal); root = insertNode(root, newVal); return root; } ``` 4. 查找节点 ```c struct TreeNode* searchNode(struct TreeNode* root, int val) { if (!root || root->val == val) { return root; } if (root->val > val) { return searchNode(root->left, val); } else { return searchNode(root->right, val); } } ``` 以上就是二叉树增删改查的C语言代码示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值