当前位置: 首页 > news >正文

[笔记] 数据结构-第九章-检索

线性表的检索

二分法检索

递归

给定的顺序表l

int BinSearch(seqlist *l,int x,int left,int right){
	if(left>right){
		return 0;
	}
	int mid=(left+right)/2;
	if(l->a[mid]==x)
		return mid;
	if(l->a[mid]>x)
		return BinSearch(l,x,left,mid-1);
	else
		return BinSearch(l,x,mid+1,right);
}

非递归

int BinSearch(seqlist *l,int x,int left,int right){
	int count=0; //计数
	while(left <= right){
		count++;
		int mid=(left+right)/2;
		if(l->a[mid]==x){
			printf("\n查找成功次数: %d \n",count);
			return mid;
		}
		if(l->a[mid]>x)
			right=mid-1;
		else
			left=mid+1;
	}
	printf("\n查找失败次数: %d\n",count);
	return -1;
}

二叉排序树

二叉排序树结构体

typedef struct k{
	int data;
	struct k* left;
	struct k* right;
}btree;

判断是否是二叉排序树

中序遍历的角度

利用中序遍历: 在中序遍历中,二叉排序树的节点值是严格递增的

int isBSTree(btree *t) {
    static btree *pre = NULL; // 静态变量,用于记录中序遍历的前驱节点
    if (t == NULL) return 1; // 空树是BST
    if (isBSTree(t->l) == 0) return 0; // 检查左子树
    if (pre != NULL && pre->data > t->data) return 0; // 检查当前节点是否满足条件, 当前节点与前驱点比较
    pre = t; // 更新前驱节点
    return isBSTree(t->r); // 检查右子树
}

定义的角度


// 找二叉树中的最大值
btree* findMax(btree *t){
	if(t==NULL)
		return NULL;
	btree* max=t;
	btree* LM=findMax(t->left);
	btree* RM=findMax(t->right);
	if(LM!=NULL && LM->data>max->data)
		max=LM;
	if(RM!=NULL && RM->data>max->data)
		max=RM;
	return max;
}

// 找二叉树中最小值
btree* findMin(btree *t){
	if(t==NULL)
		return NULL;
	btree* min=t;
	btree* Lm=findMin(t->left);
	btree* Rm=findMin(t->right);
	if(Lm!=NULL && Lm->data<min->data)
		min=Lm;
	if(Rm!=NULL && Rm->data<min->data)
		min=Rm;
	return min;
}

//判断是否是二叉树(递归)
int isBST(btree *t){
	if(t==NULL)
		return 1; //空数为二叉树
	btree* L_max=findMax(t->left);   //找左子树的最大值
	btree* R_min=findMin(t->right); //找右子树的最小值
	
	// 如果左子树的最大值大于当前节点的值,或者右子树的最小值小于当前节点的值,则不是二叉排序树
	if((t->left!=NULL && t->data<=L_max->data) || (t->right!=NULL && t->data >= R_min->data) )
		return 0;
	//递归遍历左右子树是否是二叉排序树
	if( isBST(t->left) && isBST(t->right) )
		return 1;
	return 0;
}

这个方法效率比较低下且看起来也比较复杂, 但感觉比较容易理解一点
改进的代码(GTP改进的)

int isBSTWithRange(btree *t, int min, int max) {
    if (t == NULL) return 1; // 空树是BST
    if (t->data <= min || t->data >= max) return 0; // 当前节点不符合范围
    // 递归检查左右子树,左子树的值必须小于当前节点值,右子树的值必须大于当前节点值
    return isBSTWithRange(t->left, min, t->data) &&
           isBSTWithRange(t->right, t->data, max);
}

int isBST(btree *t) {
    return isBSTWithRange(t, INT_MIN, INT_MAX); // 初始范围为整型的最小值到最大值
}

二叉排序树–插入结点

递归

btree *InsertBSTree(btree *t, int x){
	btree *q;
	if(t==NULL){
		q=(btree *)malloc(sizeof(btree));
		q->data=x;
		q->left=NULL;
		q->right=NULL;
		return q;
	}
	if(x<=t->data)//x小就递归遍历左子树,否则就右子树
		t->left=InsertBSTree(t->left,x);
	else
		t->right=InsertBSTree(t->right,x);
	return t;
}

非递归

btree *InsertBSTree(btree *t, int x){
	btree *p,*pre,*q;
	q=(btree *)malloc(sizeof(btree));
	q->data=x;
	q->left=NULL;
	q->right=NULL;
	if(t==NULL)
		return q;
	p=t;
	pre=NULL;
	while(p!=NULL){//查找插入点
		pre=p;
		if(x<=p->data) 
			p=p->left;
		else
			p=p->right;
	}
	if(x<=pre->data)//x小就插入到左边, 否则插入到右边
		pre->left=q;
	else
		pre->right=q;	
	
	return t;
}

建树(基于插入操作建树)

// 2.2输入一组数据,基于上面插入操作建树(非递归)
void BuildTree(btree **t,int a[], int n){
	for(int i=0;i<n;i++){
		*t=InsertBSTree(*t,a[i]);
	}
}

二叉排序树中查找元素x

递归

btree *Find(btree *t,int x){
	if(t==NULL || t->data==x)
		return t;
	if(x<t->data)
		return Find(t->left,x);
	else
		return Find(t->right,x);
	return NULL;//未找到返回NULL
}

非递归

btree *Find2(btree *t,int x){
	while(t!=NULL){
		if(t->data==x)
			return t;
		if(x<t->data)
			t=t->left;
		else
			t=t->right;
	}
	return NULL;
}

散列检索

创建hash表

//hash散列表, 取key的十位数作哈希地址,采用线性探测法作为冲突处理方法
void hash(int num[],int h[],int size){
	//初始化
	for(int i=0;i<10;i++) //hash表存10个数据
		h[i]=-1;
	//填入数据
	for(int i=0;i<size;i++){
		int pos=(num[i]/10)%10;//取十位数为hash的key
		while(h[pos]!=-1){//冲突处理
			pos++;
			if(pos==10)
				pos=0;
		}
		h[pos]=num[i];	
	}
		
}


查找值x

//查找 ,线性探测法作为冲突处理方法
void search(int h[],int x){
	int pos,count=0;
	pos=(x/10)%10;//hash的key
	while(h[pos]!=x){
		if(h[pos]==-1){
			printf("找不到值 %d,查找次数 %d",x,count+1);
			return;
		}
		pos++;
		if(pos==10)//数组大小为10
			pos=0;
		count++;
	}
	printf("找到值%d ,查找次数为%d",x,count+1);
}

平均查找长度

void avgCount(int h[],int num[],int size){
    int i,j,pos,count=0,totalCount=0,notFoundTotalCount=0;
    for(i=0;i<size;i++){
        pos=(num[i]/10)%10;
        count=1;
        while(h[pos]!=num[i]){
            pos++;
            if(pos==10) pos=0;
            count++;
        }
        totalCount+=count;
    }
    for(i=0;i<10;i++){
        pos=i;
        count=1;
        while(h[pos]!=-1){
            pos++;
            if(pos==10) pos=0;
            count++;
        }
        notFoundTotalCount+=count;
    }
    printf("平均查找长度(找到):%f",(float)totalCount/size);
    printf("(找不到):%f\n",(float)notFoundTotalCount/10);
}

相关文章:

  • eBPF调研-附上参考资源
  • 人工智能之数学基础:齐次方程组和非齐次方程组的区别
  • java+selenium(资源全备,打开已使用浏览器信息,保留用户信息)
  • Day21:二叉树的深度
  • 知行之桥EDI系统应用程序目录切换指南(Windows与跨平台版)
  • Java-SpringBootWeb入门、Spring官方脚手架连接不上解决方法
  • 使用Three.js渲染器创建炫酷3D场景
  • 74HC04(反相器)和74HC14(反相器、施密特触发器)的区别
  • 【项目】幸运抽奖 测试报告
  • 怎么查看linux是Ubuntu还是centos
  • Compose 实践与探索十五 —— 自定义触摸
  • Python 应用部署云端实战指南 —— AWS、Google Cloud 与 Azure 全解析
  • 学习threejs,使用TextGeometry文本几何体
  • MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part11
  • Springboot各版本与Java JDK的对应关系及JDK商用版本
  • 【JavaWeb学习Day27】
  • 洛谷 P2157 [SDOI2009] 学校食堂
  • C++从入门到实战(六)类和对象(第二部分)C++成员对象及其实例化,对象大小与this详解
  • pytorch 网络结构可视化Netron安装使用方法(已解决)
  • 人力资源管理基于SpringBootSSM框架
  • 公示资费套餐、规范营销行为,今年信息通信行业将办好这十件实事
  • 陶石不语,玉见文明:临平玉架山考古博物馆明日开馆
  • 新闻1+1丨强对流天气频繁组团来袭,该如何更好应对?
  • 乌克兰官员与法德英美四国官员举行会谈
  • 中国情怀:时代记录与家国镜相|澎湃·镜相第三届非虚构写作大赛暨七猫第六届百万奖金现实题材征文大赛征稿启事
  • 上海虹桥国际咖啡文化节开幕,推出茶咖文化特色街区、宝妈咖啡师培训