小代码 向原文学习 BST 简单的C语言版本

 
 /********************************
 运行环境:http://www.anycodes.cn/zh/
 原文:http://blog.csdn.net/u014488381/article/details/41719765/
 二叉排序树的查找算法的C代码实现
 修改以直接测试
 待C++类封装版本
 *********************************/
#include <stdio.h>
#include <stdlib.h>
typedef int Elemtype;
typedef struct BiTNode{
	Elemtype data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

/*/在给定的BST中插入结点,其数据域(数值)为element/*/
void BSTInsert( BiTree *t, Elemtype element )
{/*/每次插入 开辟空间/*/
	if( NULL == *t ) {
		(*t) = (BiTree)malloc(sizeof(BiTNode));
		(*t)->data = element;
		(*t)->lchild = (*t)->rchild = NULL;
	}
/*/依据二叉搜索树性质/*/
	if( element == (*t)->data ) return ; /*/不允许有重复的数据,若遇到直接不处理/*/
	else if( element < (*t)->data ) BSTInsert( &(*t)->lchild, element );
	     else                       BSTInsert( &(*t)->rchild, element );
}

/*/创建BST/*/
void CreateBST( BiTree *t, Elemtype *a, int n )
{
	(*t) = NULL;
	for( int i=0; i<n; i++ )
		BSTInsert( t, a[i] );
}

/*/BST的递归查找/*/
void SearchBST( BiTree t, Elemtype key )
{
	BiTree p;  p = t;
	if( p ) {
		if( key == p->data )
			printf("查找成功!\n");
		else if( (key < p->data) && (NULL != p->lchild) )
			SearchBST( p->lchild , key );
		else if( (key > p->data) && (NULL != p->rchild) )
			SearchBST( p->rchild , key );
		else
			printf("无此元素!\n");
	}
}

/*/BST的迭代查找/*/
void _SearchBST( BiTree t, Elemtype key )
{
	BiTree p;  p = t;
	while( NULL != p && key != p->data ) /*/结点存在而数值不等时/*/
	{
		if( key < p->data )  p = p->lchild ;
		 else 	         	p = p->rchild ;
	}/*/ 走出循环后 p指针总是指向找到的元素 或者 叶子结点下的空结点/*/
	if( NULL != p ) printf("查找成功!\n");
	 else    	    printf("无此元素!\n");
}

/*/BST结点的删除    本二叉树内容重点/*/
void DelBSTNode( BiTree t, Elemtype key )
{
	BiTree p, q;
	p = t;
	Elemtype temp;
	/*/ 先遍历找这元素/*/
	while( NULL != p && key != p->data ) {
		q = p; /*/ q总是在结点p的上方(当p不是根结点时q总是父亲)
             p就是我们要删的元素
		/*/
		if( key < p->data )			p = p->lchild ;
		else		p = p->rchild ;
	}
	if( NULL == p )  printf("无此元素!\n");
	/*/找到元素  会有如下几个情况
     1.         2.              3.
      q            q                   q
      /\          / \                 /  \  
     p  p        p   p               p     p
	             /     \             / \   / \  
	            x       x           x   x  x  x
	 /*/        
	else {
		/*/情况1:结点p的双亲结点为q,且p为叶子结点,则直接将其删除。/*/
		if( NULL == p->lchild && NULL == p->rchild ) {
			if( p == q->lchild ) q->lchild = NULL;
			if( p == q->rchild ) q->rchild = NULL;
			free(p);
			p = NULL;
		}
		/*/情况2:结点p的双亲结点为q,且p只有左子树或只有右子树,
		则可将p的左子树或右子树直接改为其双亲结点q的左子树或右子树。/*/
		else if( (NULL == p->rchild && NULL != p->lchild) ) {	/*/p只有左子树/*/
			if( p == q->lchild )				q->lchild = p->lchild ;
			else if( p == q->rchild )			q->rchild = p->lchild ;
			free(p);
			p = NULL;
		}
		else if( NULL == p->lchild && NULL != p->rchild ) {		/*/p只有右子树/*/
			if( p == q->lchild )				q->lchild = p->rchild ;
			if( p == q->rchild )				q->rchild = p->rchild ;
			free(p);
			p = NULL;
		}
		/*/情况3:结点p的双亲结点为q,且p既有左子树又有右子树。
		本代码使用直接前驱(也可以直接后继)这里找的是左子树中最大的元素/*/
		else if( NULL != p->lchild && NULL != p->rchild ) {
				BiTree s, sParent;
				sParent = p;
				s = sParent->lchild ;
				while( NULL != s->rchild )	{/*/找到p的直接前驱/*/
					sParent = s;
					s = s->rchild ;	      /*/左子树最大的总是在左子树中最右下角/*/
				}
				temp = s->data ;	    /*/此时 s指向的是最大的右下叶子结点 为一般情况1 直接删除/*/
				DelBSTNode( t, temp );
				p->data = temp;   /*/最后将原来要删除的p的数据改为temp/*/
		}
	}

}

/*/
待递归版本的删除 传引用的妙处
中序遍历打印BST/*/
void PrintBST( BiTree t )
{
	if( t ) {
		PrintBST( t->lchild );
		printf("%d ", t->data);
		PrintBST( t->rchild );
	}
}

void use()
{
	int n;
	int *a;
	Elemtype key;
	BiTree t;

	printf("请输入二叉查找树的结点数:\n");
	scanf("%d", &n);

	a = (int *)malloc(sizeof(int)*n);
	printf("请输入二叉找树的结点数据:\n");
	for( int i=0; i<n; i++ )
		scanf("%d", &a[i]);
	CreateBST( &t, a, n );
	printf("当前二叉查找树的中序遍历结果为:\n");
	PrintBST( t );
	printf("\n##############################################\n");

	printf("请输入要查找的元素:\n");
	scanf("%d", &key);
	printf("BST递归查找结果:\n");
	SearchBST( t, key );		//递归查找

	printf("##############################################\n");
	printf("请输入要删除的元素:\n");
	scanf("%d", &key);
	DelBSTNode( t, key );
	printf("当前二叉查找树的中序遍历结果为:\n");
	PrintBST( t );
	printf("\n##############################################\n");

	printf("请输入要查找的元素:\n");
	scanf("%d", &key);
	printf("BST迭代查找结果:\n");
	_SearchBST( t, key );		//迭代查找
 
}
void test()
{
	int n;  
	Elemtype key;   BiTree t;
    int a[]={5,8,2,1,4,7,9,6,3};
	printf("请输入二叉查找树的结点数:\n");
    n=9;
	printf("请输入二叉找树的结点数据:\n");
	CreateBST( &t, a, n );
	printf("当前二叉查找树的中序遍历结果为:\n");
	PrintBST( t );
	printf("\n##############################################\n");

	printf("请输入要查找的元素:\n");
	key=8;
	printf("BST递归查找结果:\n");
	SearchBST( t, key );		//递归查找

	printf("##############################################\n");
	printf("请输入要删除的元素:\n");
	 key=5;
	DelBSTNode( t, key );
	printf("当前二叉查找树的中序遍历结果为:\n");
	PrintBST( t );
	printf("\n##############################################\n");

	printf("请输入要查找的元素:\n");
	 key=5;
	printf("BST迭代查找结果:\n");
	_SearchBST( t, key );		//迭代查找
 
}
int main(void)
{
	printf("Hello,C world of AnycodeX!\n");
	test();
	return EXIT_SUCCESS;
}
时间: 2024-08-10 21:29:34

小代码 向原文学习 BST 简单的C语言版本的相关文章

小代码 向原文学习 对AVL树的4种情况 用字母标记整理

   /******************  环境:http://anycodes.cn/zh/  AVL  有高度标签    红黑树 更有颜色标记  http://blog.csdn.net/whucyl/article/details/17289841  我们总是以ABC 3个结点为例子 插入元素后C总是不平衡的  LL RR 较为简单   交换后C还是出于下方  LR RL 统一的一句就是  C总提出交换子树,要翻身做了老大.  LL LR与 RR RL是对称的4种情况写了前2种就能写出

小代码 向高手学习基树

 /*****************  运行 环境:http://www.anycodes.cn/zh/  内容: 基数树    *******************/  #include <stdio.h> #include <stdlib.h> typedef struct RadixNode {     char *str;      struct RadixNode *lchild, *rchild;  } RadixNode; void radix_insert(Ra

java学习中,DVD管理系统纯代码(java 学习中的小记录)

java学习中,DVD管理系统纯代码(java 学习中的小记录)作者:王可利(Star·星星) class DvdMain{ public static void main (String[] args){ DvdMgr dvd = new DvdMgr(); //初始化dvd dvd.initial(); //开始进入切换菜单 dvd.startMenu(); } } 1 class DvdSet { 2 3 //定义三个属性 4 String[] name = new String[50];

微信小程序开发:学习笔记[2]——WXML模板

微信小程序开发:学习笔记[2]--WXML模板 快速开始 介绍 WXML 全称是 WeiXin Markup Language,是小程序框架设计的一套标签语言,结合小程序的基础组件.事件系统,可以构建出页面的结构. 打开开发工具的编辑器,在根目录下找到 app.json 文件,双击打开,在 "pages/index/index" 上新增一行 "pages/wxml/index" 保存文件.模拟器刷新后,读者可以在编辑器中找到 pages/wxml/index.wxm

微信小程序开发:学习笔记[3]——WXSS样式

微信小程序开发:学习笔记[3]--WXSS样式 快速开始 介绍 WXSS(WeiXin Style Sheets)是一套用于小程序的样式语言,用于描述WXML的组件样式,也就是视觉上的效果. WXSS与Web开发中的CSS类似.为了更适合小程序开发,WXSS对CSS做了一些补充以及修改. 文件组成 项目公共样式:根目录中的app.wxss为项目公共样式,它会被注入到小程序的每个页面. 页面样式:与app.json注册过的页面同名且位置同级的WXSS文件.比如注册了pages/rpx/index页

结对编程项目:带UI的小初高数学学习软件

用户: 小学.初中和高中学生. 功能: 1.用户注册功能. 2.登录,修改密码 3.在线做题,评分 经验总结 这次的结对编程并没有实现对个人项目的复用,经过对结对编程需求的分析发现个人项目的出题逻辑完全不能用于小初高数学学习软件, 因为在个人项目中的出题逻辑是几乎是采用的完全随机,在结对编程项目中这种逻辑是行不通的,没有办法采用答案,而且在个人项目中我们 都是采用的面向过程的方法,同时我们的个人项目结构也有点混乱,导致了复用的难度很大.所以我们完全重新写了代码,实现了登录/注测, 修改密码,选择

窦小凤2020寒假学习心得

2020年1-2月寒假学习心得—窦小凤 一.学习成果 赛事准备上,每天坚持做题,完成代码量6000行(其中还包括了很多知识点学习上的代码). 学习python基础,对python有了基本认识,完成代码1500行(但其中基本都是python中的基础语法) 选择性学习了一些用Java语言讲的数据结构与算法. 前期主要是将Java的基础视频重看了一遍(主要是在学校的时候没认真),然后从最基础入门开始做起,到寒假末来看,自身在Java方面跟在大一上学期还是有较大进步,但仍还有很长的路要走. Python

从零开始--系统深入学习android(实践-让我们开始写代码-Android框架学习-7.通知)

通知 一个通知是一条消息他是显示于你应用程序之外的一个界面中.当你告诉系统要发布一个通知时,它首先作为一个icon出现在通知区域.为了看见通知的细节,用户可以点击通知区域展开一个新的界面.下面让我们来看一下图7-1和图7-2: 图7-1 通知出现在通知区域 图7-2 通知展开后的效果(drawer) 注意:除非特别注明外,本章指的都是NotificationCompat.Builder,它在v4 Support Library中有,正式添加于API Level 15.但有了v4 Support

微信小程序开发:学习笔记[1]——Hello World

微信小程序开发:学习笔记[1]--Hello World 快速开始 1.前往微信公众平台下载微信开发者工具. 地址:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html 2.打开微信开发者工具,并新建项目 打开微信开发者工具,选择新建小程序项目,我们先不需理解AppID的概念,新建项目时选择无AppID,并取消勾选"建立普通快速启动模板"的选项. 3.在根目录添加代码 1.在根目录创建app.json文件 2.