动态查找——二叉排序树

1.问题描述:

判别一棵二叉树是否为二叉排序树,如果是,在其上实现查找功能。

2.实验要求:

(1)以二叉链表为存储结构,创建二叉树;

(2)设计判别算法;

(3)输入所要查找表的数据;

(4)输出判别结果;

3.程序实现:

(1)代码:

#include <iostream>
using namespace std;
int i = 0;
typedef struct BitNode 
{
    int data;
    struct BitNode* lchild, * rchild;
}BitNode, * BiTree;

//二叉排序树的创建
void insert(BitNode*& p, int a)//引用型,需要改变p的内容
{
	if (p == NULL)//找到了空指针,存放关键字
	{
		p = new BitNode;
		p->data = a;
		p->lchild = NULL;
		p->rchild = NULL;
	}
	else if (p->data < a)//如果待插入关键字较大,则插入右子树
	{
		insert(p->rchild, a);
	}
	else//否则左子树
	{
		insert(p->lchild, a);
	}
}

//利用数组依次输入二叉排序树的结点元素值
void createBst(BitNode*& T, int a[], int n) 
{
	T = NULL;
	cout << "输入结点值:";
	int i;
	for (i = 0; i < n; i++) 
	{
		cin >> a[i];
		insert(T, a[i]);
	}
}


//中序遍历
void inOrderTraverse(BiTree T)
{
	if (T)
	{
		inOrderTraverse(T->lchild);
		cout<< T->data<<'\t';
		inOrderTraverse(T->rchild);
	}
}

//查找给定的元素
void searchBst(BiTree T, int key) 
{
	//记录第几次查找到 
	++i;
	if (T) {
		if (key == T->data) 
		{
			cout<<"第"<<i<<"次查询\n";
			cout<<"查得:"<< T->data;
		}
		else if (key < T->data)   //所查值<根值,左子树上进行查找
			searchBst(T->lchild, key);
		else      //所查值>根值,右子树上进行查找
			searchBst(T->rchild, key);
	}
}


int main()
{
	int a[100];
	BiTree T;
	int n; cout << "输入二叉排序树结点个数:";
	cin >> n;
	createBst(T, a, n);
	cout << "中序遍历结果:";
	inOrderTraverse(T);
	cout << endl;
	cout << "二叉排序树的判断:yes\n";//判断结果必定为yes,因为此代码在输入元素的同时就创建二叉排序树
	int b;
	cout << "输入要查找的元素:";
	cin >> b;
	searchBst(T, b);
	return 0;
}

 (2)建立的模型及存储结构

以二叉链表为存储结构直接创建二叉排序树。该程序未创建二叉树,再判断二叉树是否是二叉排序树。

若要先创建二叉树再判断,可以用如下方法:

(1)中序遍历二叉树的同时,用数组b记录每一次遍历的元素。然后判断数组b是否是升序,如果符合升序,则该二叉树为二叉排序树。

int i=0;int b[100];
int t;
~~~~~~~~~~
void inOrderTraverse(BiTree T)
{
	if (T)
	{
		inOrderTraverse(T->lchild);
		cout<< T->data<<'\t';
        b[i]=T->data;i++;
		inOrderTraverse(T->rchild);
	}
}
void judge(b)
{
   for(int j=0;j<i-1;j++)
     if(b[j]>b[j+1])
      {cout<<"NO"<<endl;t=0}
}
int main()
{
~~~~~
void judge(b)
if(!t)cout<<"YES"<<endl;
~~~~~
}

(2)比较二叉树每个结点是否符合左子树<根<右子树。

int SelectBinSortTree(BinTreeNode *T)//判断是否为二叉排序树
{
    if(T==0) return 1;
    else if(T->Lchild&&T->Rchild)
    {
        if(T->data<T->Lchild->data||T->data>T->Rchild->data) return 0;
        else return(SelectBinSortTree(T->Lchild)&&SelectBinSortTree(T->Rchild));
    }
    else if(T->Lchild)
    {
        if(T->data<T->Lchild->data) return 0;
        else return(SelectBinSortTree(T->Lchild));
    }
    else if(T->Rchild)
    {
        if(T->data<T->Rchild->data) return 0;
        else return(SelectBinSortTree(T->Rchild));
    }
    return 1;
}

4.测试与运行:

076587df7a6a4a98ad36a1c75849b2cd.png

 (1)查找50:

9361bb5e600c45bc9837a05d67657ec2.png

 (2)查找40:

a05478c5487241e4821cdbf732529426.png

  5.思考题:

(1)若二叉排序树各个结点的值都不相同,试设计算法,按升序打印出该二叉树各个节点的值。

void inOrderTraverse(BiTree T)
{
	if (T)
	{
		inOrderTraverse(T->lchild);
		cout<< T->data<<'\t';
		inOrderTraverse(T->rchild);
	}
}

(2)计算二叉排序树的平均查找长度。

查找成功的平均查找长度为:∑(本层高度*本层元素个数)/节点总数

查找不成功的平均查找长度:∑(本层高度*本层补上的叶子个数)/补上的叶子总数

076587df7a6a4a98ad36a1c75849b2cd.png

 查找成功的平均查找长度为:(1+2*2+3*3)/6

查找不成功的平均查找长度:(2+3*6)/7

6.实验心得体会:

熟悉二叉排序树的创建,查找,删除,插入。知道如何定义节点结构。

typedef有取别名的作用,所以BitNode的意思是struct BitNode{...),BiTree的意思是struct BitNode{...)*。

BiTree &T 是取指针地址的意思,如同int  &a,取a得地址一样。

BitNode *T  和  BiTree T 是定义结构指针变量。

参数BiTree &T也可用写成BitNode *(&T)

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
搜索,也叫二查找(BST,Binary Search Tree),是一种特殊的二。相对于普通的二,它有一个特点:所有左子的节点都比根节点小,所有右子的节点都比根节点大。因此,它可以快速地进行查找、插入、删除等操作。 具体来说,二搜索的定义如下: - 节点的左子中所有节点的值都小于该节点的值。 - 节点的右子中所有节点的值都大于该节点的值。 - 左右子也都是二搜索。 如下图所示,就是一个二搜索的例子: ``` 8 / \ 3 10 / \ \ 1 6 14 / \ / 4 7 13 ``` 在这个中,每个节点都满足左子的节点值小于该节点的值,右子的节点值大于该节点的值。比如,节点 3 的左子是 1 和 6,右子是 4 和 7,都满足要求。 二搜索的主要操作包括查找、插入和删除。 查找操作可以通过递归或者循环实现。递归实现如下: ``` def search(root, val): if not root or root.val == val: return root if root.val > val: return search(root.left, val) else: return search(root.right, val) ``` 插入操作需要先查找到插入的位置,然后创建一个新节点插入到该位置: ``` def insert(root, val): if not root: return TreeNode(val) if root.val > val: root.left = insert(root.left, val) else: root.right = insert(root.right, val) return root ``` 删除操作比较复杂,需要考虑多种情况。如果要删除的节点只有一个子节点,直接将其子节点替换上来即可。如果要删除的节点有两个子节点,可以找到其右子中的最小节点(或者左子中的最大节点)来替换该节点,然后再删除该最小节点(或者最大节点)。 ``` def delete(root, val): if not root: return None if root.val == val: if not root.left: return root.right elif not root.right: return root.left else: # 找到右子中的最小节点 p = root.right while p.left: p = p.left root.val = p.val root.right = delete(root.right, p.val) elif root.val > val: root.left = delete(root.left, val) else: root.right = delete(root.right, val) return root ``` 需要注意的是,在删除节点时,要保证删除后的仍然是二搜索

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SweetCinderella

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值