数据结构总结17——查找1——查找算法实现(顺序、折半、二叉排序树、平衡二叉树、哈希表) by DexterYan

一、基础知识

二、代码要求

三、算法思路分析

四、算法反思

五、代码实现

  1. 顺序查找
#include<stdio.h>
int search(int a[], int y, int x); /*对自定义的函数search进行声明*/
int main(void)
{
    int i, x, n, num; /*变量定义*/
    int a[100];
    printf("请输入数组的长度:");
    scanf("%d",&num);
    printf("请输入%d个数字!\n",num);
    for(i = 0; i < num; i++)
        {
            scanf("%d", &a[i]);   /*接收输入的数组*/
        }
    printf("请输入要查找的数:");
    scanf("%d", &x); /*接收关键字*/
    n = search(a, 10, x); /*调用函数search()完成顺序查找*/
    if(n < 0) /*输出要找的数的位置*/
        {
            printf("没找到您要找的数,您要找的数可能不在数组中。\n");
        }
    else
        {
            printf("您要找的数%d在数组中第%d个元素处。\n", x, n);
        }
}
//顺序查找
int search(int a[], int y, int x) /*被调用的函数search()*/
{
    int i, f = -1;
    for(i = 0; i < 10; i++)
        {
            if(x == a[i])//查找到所需的元素,跳出循环
                {
                    f = i + 1;
                    break;
                }
        }
    return(f);
}
  1. 折半查找
#include <stdio.h>
int binary_search(int key,int a[],int n) //自定义函数binary_search()
{
    int low,high,mid,count=0,count1=0;
    low=0;
    high=n-1;
    while(low<high)    //査找范围不为0时执行循环体语句
    {
        count++;    //count记录査找次数
        mid=(low+high)/2;    //求中间位置
        if(key<a[mid])    //key小于中间值时
            high=mid-1;    //确定左子表范围
        else if(key>a[mid])    //key 大于中间值时
            low=mid+1;    //确定右子表范围
        else if(key==a[mid])    //当key等于中间值时,证明查找成功
        {
            printf("查找成功!\n 查找 %d 次!a[%d]=%d",count,mid,key);    //输出査找次数及所査找元素在数组中的位置
            count1++;    //count1记录查找成功次数
            break;
        }
    }
    if(count1==0)    //判断是否查找失敗
        printf("查找失敗!");    //査找失敗输出no found
    return 0;
}
int main()
{
    int i,key,a[100],n;
    printf("请输入数组的长度:\n");
    scanf("%d",&n);    //输入数组元素个数
    printf("请输入数组元素:\n");
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);    //输入有序数列到数组a中
    printf("请输入你想查找的元素:\n");
    scanf("%d",&key);    //输入要^找的关键字
    binary_search(key,a,n);    //调用自定义函数
    printf("\n");
    return 0;
}
  1. 二叉排序树
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
	int key;
	struct node *lchild, *rchild;
}BSTNode, *BSTree;
 
//插入
int InsertBST(BSTree *bst, int k)
{
	BSTree r, s, pre;
	r = (BSTree)malloc(sizeof(BSTNode));
	r->key = k;
	r->lchild = NULL;
	r->rchild = NULL;
	if(*bst == NULL)
	{
		*bst = r;
		return 1;
	}
	pre = NULL;
	s = *bst;
	while(s)
	{
		if(k == s->key)
				return 0;
		else if(k < s->key)
		{
			pre = s;
			s = s->lchild;
		}
		else
		{
			pre = s;
			s = s->rchild;
		}
	}
	if(k < pre->key)
			pre->lchild = r;
	else
			pre->rchild = r;
	return 1;
}	
 
 
void CreateBST(BSTree *bst)
{
	int key;
	*bst = NULL;
	scanf("%d", &key);
	while(key != -1)
	{
		InsertBST(bst, key);
		scanf("%d", &key);
	}
}
 
/*
 *打印二叉树:
 *中序遍历
*/
void InOrder(BSTree root)
{
	if(root != NULL)
	{
		InOrder(root->lchild);
		printf(" %d ", root->key);
		InOrder(root->rchild);
	}
}
 
/*
 *搜索
 */
BSTree SearchBST(BSTree bst, int key)
{
	BSTree q;
	q = bst;
	//递归
	while(q)
	{
			if(q->key == key)
					return q;
			if(q->key > key)
					q=q->lchild;
			else
					q=q->rchild;
	}
	return NULL;                        //查找失败
}
 
int main()
{
	BSTree T;
	int tag = 1;
	int m, n;
	printf("建立二叉排序树,请输入序列以-1结束:\n");
	CreateBST(&T);
	printf("中序遍历二叉树,序列为:\n");
	InOrder(T);
	printf("\n");
	while(tag != 0)
	{
		printf("请输入你要查找的元素:\n");
		scanf("%d", &n);
		if(SearchBST(T, n) == NULL)
				printf("抱歉查找失败!\n");
		else
				printf("查找成功!查找的数字为%d\n", SearchBST(T,n)->key);
		printf("是否继续查找 是 :请按 1 否则按 0:\n");
		scanf("%d", &tag);
	}
	return 0;
}
  1. 平衡二叉树
#include<stdio.h>
#include<stdlib.h>
#define MAX 50
#define nul -32768

typedef struct Node    //树中结点的定义 
{
	int key;    //关键字 
	struct Node *pleft;    //指向左子树的指针 
	struct Node *pright;    //指向右子树的指针
	int bf;    //表示该结点的平衡因子 
}Node;

typedef struct Hash
{
	int *e;   //数据元素存储基地址,动态分配数组
	int count;   //当前数据元素个数
}Hash;
int l=0;   //散列表长,全局变量

void menu();

//顺序查找
int SeqSearch(int a[],int n,int k)
{
	int i;
	for(i=0;i<n;i++)
	{
		if(a[i]==k)
		{
			return i;
		}
	}
	return -1;
}

//折半查找,要求查找表有序 
int BinarySearch(int a[],int n,int k)
{
	int l=0,h=n-1,m;
	while(l<=h)
	{
		m=(l+h)/2;
		if(k==a[m])
		{
			return m;
		}
		if(k<a[m])
		{
			h=m-1;
		}
		else
		{
			l=m+1;
		}
	}
	return -1;
}

//二叉排序树
//查找
int SearchBS(Node *BT,int key)
{
	if(BT==NULL)
	{
		return 0;
	}
	if(key==BT->key)
	{
		return 1;
	}
	else if(key<BT->key)
	{
		return SearchBS(BT->pleft,key);
	}
	else
	{
		return SearchBS(BT->pright,key);
	}
} 
int SearchBST(Node *BT,int key,Node **k,Node **parent)
{
	*k=BT;
	while(*k)
	{
		if(key>(*k)->key)
		{
			*parent=*k;
			*k=(*k)->pright;
		}
		else if(key<(*k)->key)
		{
			*parent=*k;
			*k=(*k)->pleft;
		}
	}
	*k=*parent;
	return 0;
}
//插入和创建
int InsertBST(Node **BT,int key)
{
	Node *s;    //定义存放新的关键字的结点
	Node *k,*parent=NULL;
	if(SearchBST(*BT,key,&k,&parent)==1)   //若关键字已在树中,则插入失败 
	{
		return 0;
	}
	//关键字不在树中,首先为新结点分配空间
	s=(Node *)malloc(sizeof(Node));
	s->key=key;
	s->pleft=s->pright=NULL;
	
	if(k==NULL)    //若树为空树,则新结点为插入后的根结点 
	{
		(*BT)=s;
	}
	else if(key<k->key)
	{
		k->pleft=s;
	} 
	else
	{
		k->pright=s;
	}
	return 1;
} 

//平衡二叉树

int SearchBalanceBST(Node *BT,int key)
{
	int f=0;
	Node *p=BT;
	while(p)
	{
		if(key>p->key)
		{
			p=p->pright;
		}
		else if(key<p->key)
		{
			p=p->pleft;
		}
	}
	return 0;
} 
//插入
void RightRotate(Node **BT)   //右旋 
{
	Node *p=(*BT)->pleft;
	(*BT)->pleft=p->pright;
	p->pright=*BT;
	*BT=p;
}
void LeftRotate(Node **BT)
{
	Node *p=(*BT)->pright;
	(*BT)->pright=p->pleft;
	p->pleft=*BT;
	*BT=p;
}
void LL_LR_Balance(Node **BT)
{
	Node *pleft=(*BT)->pleft;
	Node *pright;
	switch(pleft->bf)
	{
		case 1:   //LL 
			(*BT)->bf=pleft->bf=0;
			RightRotate(BT);
			break;
		case -1:    //LR
			pright=pleft->pright;
			switch(pright->bf)
			{
				case 0:
					(*BT)->bf=pleft->bf=0;
					break;
				case 1:
					pright->bf=pleft->bf=0;
					(*BT)->bf=-1;
					break;
				case -1:
					(*BT)->bf=pright->bf=0;
					pleft->bf=1;
					break;
			}
			LeftRotate(&(*BT)->pleft);
			RightRotate(BT);
			break;
	}
}
void RR_RL_Balance(Node **BT)
{
	Node *pright=(*BT)->pright;
	Node *pleft;
	switch(pright->bf)
	{
		case -1:    //RR
			(*BT)->bf=pright->bf=0;
			LeftRotate(BT);
			break;
		case 1:    //RL
			pleft=pright->pleft;
			switch(pleft->bf)
			{
				case 0:
					(*BT)->bf=pright->bf=0;
					break;
				case 1:
					(*BT)->bf=pleft->bf=0;
					pright->bf=-1;
					break;
				case -1:
					pright->bf=pleft->bf=0;
					(*BT)->bf=1;
					break;
			}
			RightRotate(&(*BT)->pright);
			LeftRotate(BT);
			break;
	}
}

/*平衡二叉树是二叉搜索树的优化版本,在算法内部他要比 二叉搜索树更加的高效.但是输出这里体现不出来*/ 
int InsertBalanceBST(Node **BT,int key,int *chain)
{
	if((*BT)==NULL)    //表示未在树中找到key,直接生成新的结点,用于存储key 
	{
		*BT=(Node *)malloc(sizeof(Node));
		(*BT)->bf=0;
		(*BT)->pleft=(*BT)->pright=NULL;
		(*BT)->key=key;
		*chain=1;    //插入新结点引起树的高度变化 
	}
	else
	{
		if(key==(*BT)->key)   //树中含相同关键字,插入失败 
		{
			*chain=0;
			return 0;
		}
		if(key<(*BT)->key)
		{
			if(!InsertBalanceBST(&(*BT)->pleft,key,chain))
			{
				return 0;
			}
			if(*chain)
			{
				switch((*BT)->bf)
				{
					case 0:
					    (*BT)->bf=1;
					    *chain=1;
					    break;
					case 1:
						LL_LR_Balance(BT);
						*chain=0;
						break;
					case -1:
						(*BT)->bf=0;
						*chain=0;
						break;
				}
			}
		}
		else
		{
			if(!InsertBalanceBST(&(*BT)->pright,key,chain))
			{
				return 0;
			}
			if(*chain)
			{
				switch((*BT)->bf)
				{
					case 0:
					    (*BT)->bf=-1;
					    *chain=1;
					    break;
					case 1:
						(*BT)->bf=0;
						*chain=0;
						break;
					case -1:
						RR_RL_Balance(BT);
						*chain=0;
						break;
				}
			}
		}
	}
	return 1;
}

int main()
{
	int s,n,i,x,m;
	int a[MAX];
	Node *BT=NULL; 
	int chain;
	while(1)
	{
		menu();
		scanf("%d",&s);
		switch(s)
		{
			case 1:
			    printf("请输入数据个数:\n");
				scanf("%d",&n);
				printf("请输入数据:(中间以空格分开)\n");
				for(i=0;i<n;i++)
				{
					scanf("%d",&a[i]);
				}
				for(i=0;i<n;i++)
				{
					InsertBST(&BT,a[i]);
				}
				
				printf("请输入要查找的数:\n");
				scanf("%d",&x);
				m=SearchBS(BT,x);
				if(m==0)
				{
					printf("在数组中找不到%d。\n",x);
				}
				else
				{
					printf("在数组中找到%d。\n",x);
				}
				break;
			case 2:
			    printf("请输入数据个数:\n");
				scanf("%d",&n);
				printf("请输入数据:(中间以空格分开)\n");
				for(i=0;i<n;i++)
				{
					scanf("%d",&a[i]);
				}
				for(i=0;i<n;i++)
				{
					InsertBalanceBST(&BT,a[i],&chain);
				}
				
				printf("请输入要查找的数:\n");
				scanf("%d",&x);
				m=SearchBS(BT,x);
				if(m==0)
				{
					printf("找不到%d。\n",x);
				}
				else
				{
					printf("找到%d。下标为%d\n",x);
				}
				break;
			 
			case 0:
				return 0;
			default:printf("输入格式非法,请重新输入选项,(0-2含)内的整数\n");break;
		} 
	}
	return 0;
}

void menu()
{
	printf("1.二叉排序树查找\n2.平衡二叉树查找\n0.退出\n");
	
}
  1. 哈希表
#include<stdio.h>
 
#define LEN 10
#define N 11
int data[100];   //原始数据;
int hash[LEN]={0};   //哈希表,初始化为0;
 
 
void Create()
{
	int i=0; 
	for(i=0;i<N;i++)  //循环将原始数据保存到哈希表中;
	{
		//将关键字插入到哈希表hash中;
		int j=data[i]%10;  //计算哈希地址;
		while(hash[j])  //元素位置已被占用;
			j=(++j)%LEN;  //线性探测法解决冲突;
		hash[j]=data[i];
	}
}
 
 
int Haxi_Sou(int key)
{
	int i=key%LEN;  //计算哈希地址;
	while(hash[i]&&hash[i]!=key)   //判断是否冲突;
		i=(++i)%LEN;   //线性探测法解决冲突;
	if(hash[i]==0)  //查找到开放单元,表示查找失败;
		return -1;  //返回失败值;
	else
		return i;   //返回对应的元素下标;
}
 
 
int main()
{
	int key, i=0, num;
	printf("请输入数据数量:");
	scanf("%d",&num);
	int j;
	printf("请输入数据:\n");
	for(j=0; j<num; j++)
	{
		scanf("%d",&data[j]);
	}
	Create();  //调用函数创建哈希表;
	printf("哈希表中各元素的值:");
	for(i=0;i<LEN;i++)
		printf("%d ",hash[i]);
	printf("\n");
	printf("输入查找的关键字;");
	scanf("%d",&key);
 
 
	int pos=Haxi_Sou(key);  //调用函数在哈希表中查找;
	if(pos>0)
		printf("查找成功,该关键字在数组中的下标为 %d !!!\n是第%d个元素",pos,pos+1);
	else
		printf("查找失败!!!");
	printf("\n");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41259302/article/details/94590533