搜索树【链式+数组】

数组

数组表示二叉树:

  • 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、删除节点

删除节点比较麻烦,但是主要有三种情况

  1. 待删的节点没有孩子:直接删除

  2. 待删的节点有右孩子:

    将右子树的最小的和根节点替换,这样才能保持二叉树还符合排序树的规则,再删除替换后的节点(注意这里要递归删除,因为可能右子树最小的值有左孩子)

  3. 待删除的节点没有右孩子,但是有左孩子:

    将左边子树最大值和根节点换,类似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
10

20


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;
} 

原文地址:https://www.cnblogs.com/biningooginind/p/12496351.html