搜索树链式+数组
Posted biningooginind
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搜索树链式+数组相关的知识,希望对你有一定的参考价值。
数组
数组表示二叉树:
- root
- left:root*2+1
- right:root*2+2
比如 0号节点的左孩子是1 右孩子是2
1号节点的左孩子是3 右孩子是4
2号节点的左孩子是5 右孩子是6
1、定义结构体
int tree[1000]={0}; //存放值的数组
const int NUL=0;//定义0为空
2、找树的最小值和最大值的节点位置
int findMin(int root) //找最小的 往左边找
{
if(tree[root*2+1]==NUL)
return root;
return findMin(root*2+1);
}
int findMax(int root) //找最小的 往左边找
{
if(tree[root*2+2]==NUL)
return root;
return findMin(root*2+2);
}
3、插入节点
void Insert(int root,int v)
{
if(tree[root]==NUL)
{
tree[root]=v;
return ;
}
else if(tree[root]>v)
{
Insert(root*2+1,v); //插入到左树
}
else
{
Insert(root*2+2,v); //插入到右树
}
}
4、判断节点是否存在
bool isExist(int root,int val) //是否存在数 二分 用循环代替递归
{
while(tree[root]!=NUL)
{
if(tree[root]==val)
return true;
if(tree[root]>val) //小的都在左边 大的都在右边
root=root*2+1;
else
root=root*2+2;
}
return false;
}
5、中序遍历:中序遍历都是顺序是有序的 降序
void PrintAll(int root)//中序遍历
{
if(tree[root]==NUL)
return;
else
{
//左中右 刚好有序
PrintAll(root*2+1);
cout<<tree[root]<<endl;
PrintAll(root*2+2);
}
}
6、删除节点
删除节点比较麻烦,但是主要有三种情况
待删的节点没有孩子:直接删除
待删的节点有右孩子:
将右子树的最小的和根节点替换,这样才能保持二叉树还符合排序树的规则,再删除替换后的节点(注意这里要递归删除,因为可能右子树最小的值有左孩子)
待删除的节点没有右孩子,但是有左孩子:
将左边子树最大值和根节点换,类似2步递归删除
代码如下:
void Delete(int root,int x)
{
if(tree[root]>x)
{
Delete(root*2+1,x); //在左边
}
else if(tree[root]<x)
Delete(root*2+2,x); //在右边
else
{
if (tree[root*2+1]==NUL && tree[root*2+2]==NUL){ //左右孩子都为空 直接删除即可
tree[root] = NUL;
}
else if(tree[root*2+2]!=NUL){ //右边孩子不为空 将右边最小的和根换 然后递归删除 因为最小的那个节点可能还有右孩子
int right_small = findMin(root*2+2);
swap(tree[root],tree[right_small]);
Delete(right_small,x);
}
else{ //右边空左边不空 则将左边最大的和根节点换 然后递归删除 因为可能左边节点有左孩子
int left_max = findMax(root*2+1);
swap(tree[root],tree[left_max]);
Delete(left_max,x);
}
}
}
7、测试代码
int main()
{
int root = 0;
Insert(root,10);
Insert(root,4);
Insert(root,8);
Insert(root,20);
Insert(root,3);
Insert(root,1);
PrintAll(root);
cout<<"-----------------"<<endl;
Delete(root,4);
Delete(root,10);
PrintAll(root);
}
1
3
4
8
1020
1
3
8
20
https://github.com/biningo/Algorithm.
---
链式结构
差不多,这里贴一下代码,由于c指针比较麻烦,所以讲删除的节点值设置为0代表删除
#include<iostream>
#include<cstdlib>
using namespace std;
#define NULL 0
struct Node {
int val;
Node* left=NULL;
Node* right=NULL;
Node* pre=NULL;
};
Node* FindMin(Node* root) { //寻找最小的节点 也就是寻找最左边的节点
if (root->left==NULL)
return root;
return FindMin(root->left);
}
Node* FindMax(Node* root) {
if(root->right==NULL)
return root;
return FindMax(root->right);
}
//-------------------插入--------------------------
void Insert(Node** root,int val) {
if(*root==NULL){
*root = (Node*)malloc(sizeof(Node));
(*root)->left = NULL;
(*root)->right= NULL;
(*root)->val = val;
return;
}
if(val>(*root)->val) //大于根 则插入到右边
Insert(&(*root)->right,val);
else if(val<(*root)->val) //小于根则插入到左边
Insert(&(*root)->left,val);
else
cout<<"节点已经存在"<<endl;
return;
}
//---------------------节点是否存在 ---------------
bool IsExist(Node* root,int val) {
if(root->val==val)
return true;
else if(val>root->val)
return IsExist(root->right,val);
else
return IsExist(root->left,val);
}
//---------------------中序遍历,有序打印------------
void PrintAll(Node* root) {
if(root==NULL)
return;
PrintAll(root->left); //遍历左子树
if(root->val!=0){
cout<<root->val<<endl; //左中右
}
PrintAll(root->right);//遍历右子树
}
//-------------------删除节点 递归版 删除的值为0-----------------------
void Delete(Node*root,int val) {
if(val>root->val)
Delete(root->right,val);
else if(val<root->val)
Delete(root->left,val);
else { //找到节点了
if(root->left==NULL && root->right==NULL){ //没有孩子 直接free
root->val=0;
}
else if(root->right!=NULL) { //有右孩子 则找右边最小的孩子替换根节点 让树仍然保持有序
Node* right_min = FindMin(root->right);
swap(root->val,right_min->val); //交换值
Delete(right_min,val); //递归删除 因为可能右边最小的节点还有右孩子
}
else { //只有左孩子 则找左边最大的和根节点互换
Node* left_max = FindMax(root->left);
swap(root->val,left_max->val);
Delete(left_max,val); //同理
}
}
}
int main(){
Node* root=NULL;
Insert(&root,10);
Insert(&root,4);
Insert(&root,8);
Insert(&root,20);
Insert(&root,3);
Insert(&root,1);
PrintAll(root);
//
cout<<"-----------------"<<endl;
Delete(root,4);
Delete(root,10);
//
//
PrintAll(root);
return 0;
}
以上是关于搜索树链式+数组的主要内容,如果未能解决你的问题,请参考以下文章