2023王道C语言训练营(二叉查找树-顺序查找-折半查找)

二叉排序树

在这里插入图片描述

二叉排序树演示视频(点击)

在这里插入图片描述

头文件
#include<stdio.h>
#include<stdlib.h>

结构体

typedef int KeyType;
typedef struct BSTNode {
	KeyType key;
	struct BSTNode* lchild, * rchild;
}BSTNode,*BiTree;

功能函数

int BST_Insert(BiTree& T, KeyType k)
//创建二叉排序树
{
	if (NULL == T)
	{
		//为新节点申请空间,第一个节点作为树根
		T = (BiTree)malloc(sizeof(BSTNode));
		T->key = k;
		T->lchild = T->rchild = NULL;
		return 1;//代表插入成功
	}
	else if (k == T->key)
		return 0;//发现相同元素就不插入
	else if (k < T->key)
		return BST_Insert(T->lchild, k);//函数调用结束后左孩子和原来的父亲会自动关联起来,引用的机制
	else
		return BST_Insert(T->rchild, k);
	
}
void Creat_BST(BiTree& T, KeyType str[], int n)
{
	T = NULL;
	int i = 0;
	while (i < n)
	{
		BST_Insert(T, str[i]);//把某一个节点放在二叉查找树当中
		i++;
	}
}
//递归算法简单,但执行效率较低,实现留给大家编写
BSTNode* BST_Search(BiTree T, KeyType key, BiTree& p)
{
	p = NULL;//存储要找的节点的父亲
	while (T != NULL && key != T->key)
	{
		p = T;
		if (key < T->key) T = T->lchild;//比当前节点小,就左边找
		else T = T->rchild;//比当前节点大,右边去
	}
	return T;

}

//书上没有二叉排序树的删除代码
void DeleteNode(BiTree& root, KeyType x)
{
	if (root == NULL)
	{
		return;
	}
	if (root->key > x)
	{
		DeleteNode(root->lchild, x);
	}
	else if (root->key < x)
	{
		DeleteNode(root->rchild, x);
	}
	else {
		//查找到了刪除节点
		if (root->lchild == NULL)
		{
			//左子树为空
			BiTree tempNode = root;//临时存着,一会free
			root = root->rchild;
			free(tempNode);
		}
		else if (root->rchild == NULL) {
			//右子树为空
			BiTree tempNode = root;//临时指针
			root = root->lchild;//右子树直接顶上去
			free(tempNode);
		}
		else {
			//左右子树都不为空
			//一般删除的策略是左子树的最大数据或右子树的最小数据
			//代替要删除的节点(这里采用查找左子树最大数据来代替删除的节点)
			BiTree tempNode = root->lchild;//保存删除的节点
			if (tempNode->rchild != NULL)
			{
				tempNode = tempNode->rchild;
			}
			root->key = tempNode->key;
			//递归
			DeleteNode(root->lchild, tempNode->key);
		}
	}
}
//中序遍历
void InOrder(BiTree p)
{
	if (p != NULL)
	{
		InOrder(p->lchild);
		printf(" %d", p->key);//等价于visit函数
		InOrder(p->rchild);
	}
};

主函数

int main()
{
	BiTree T=NULL;//树根
	BiTree parent;//存储父亲节点的地址值
	BiTree search;
	KeyType str[] = { 54,20,66,40,28,79,58 };//将要进入二叉排序树的元素值
	Creat_BST(T, str, 7);
	InOrder(T);
	printf("\n");
	search = BST_Search(T, 40, parent);
	if (search)
	{
		printf("找到对应节点,值=%d\n", search->key);
	}
	else {
		printf("未找到对应节点\n");
	};
	DeleteNode(T, 54);//删除某个节点
	InOrder(T);
	printf("\n");
	system("pause");
}

在这里插入图片描述


顺序查找和折半查找

在这里插入图片描述
在这里插入图片描述

头文件
#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

存储结构

typedef int ElemType;
typedef struct {
	ElemType* elem;//整型指针
	int TableLen;//存储动态数组里面元素的个数
}SSTable;

主要函数

int Search_Seq(SSTable ST, ElemType key)
{
	ST.elem[0] = key;
	int i;
	for (i = ST.TableLen - 1; ST.elem[i] != key; --i);
	return i;
}
void ST_Init(SSTable& ST, int len)
{
	ST.TableLen = len + 1;//多申请一个位置,为了哨兵
	ST.elem = (ElemType*)malloc(sizeof(ElemType) * ST.TableLen);
	int i;
	srand(time(NULL));//随机数生成
	for (int i = 0; i < ST.TableLen; i++) //为啥这里零号位置也随机了数据,为折半查找服务
	{
		ST.elem[i] = rand() % 100;
	}
}
void ST_print(SSTable ST)
{
	for (int i = 0; i < ST.TableLen; i++)
	{
		printf("%3d", ST.elem[i]);
	}
	printf("\n");
}
//时间复杂度 logn
int Binary_search(SSTable L, ElemType key)
{
	int low = 0, high = L.TableLen - 1, mid;
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (L.elem[mid] == key)
		{
			return mid;
		}
		else if(L.elem[mid]>key)
		{
			high = mid - 1;
		}
		else
			low = mid + 1;
	}
	return -1;
}

int compare(const void* left, const void* right)
//left,right是任意两个元素的地址值
{
	//转成整型指针在取值
	//从小到大排序
	return *(ElemType*)left - *(ElemType*)right;
}

主函数

//顺序查找与折半查找
int main()
{
	SSTable ST;
	ElemType key;
	int pos;//存储查询元素的位置
	ST_Init(ST, 10);
	ST_print(ST);
	printf("请输入要搜索的key的值:\n");
	scanf("%d", &key);
	pos = Search_Seq(ST, key);
	if (pos)
	{
		printf("查找成功,位置为 %d\n", pos);
	}
	else {
		printf("查找失败\n");
	}
	//compare:比较规则,需要我们传递一个函数名
	qsort(ST.elem, ST.TableLen, sizeof(ElemType), compare);//qsort实现的是快排
	ST_print(ST);
	printf("二分查找,请输入要搜索的key的值:\n");
	scanf("%d", &key);
	//有序数组,必须是数组,链表不能随机访问
	pos = Binary_search(ST, key);//二分查找,也叫折半查找
	if (pos != 1)
	{
		printf("查找成功 位置为 %d\n", pos);
	}
	else {
		printf("查找失败\n");
	}
	system("pause");
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值