查找与排序的常用算法

目录

1.查找

常用的查找算法

1.1顺序查找

1.2折半查找

1.3分块查找

1.4Hash查找

2.排序

常用的排序方法

2.1冒泡排序

2.2选择排序

2.3插入排序

2.3.1直接插入排序

2.3.2希尔排序

2.4快速排序


1.查找

常用的查找算法

顺序查找、折半查找、分块查找、Hash查找

1.1顺序查找

顺序查找就是从头到尾遍历一遍,找到就返回所找值的下标

/*===============================================
*   文件名称:shunxuchazhao.c
*   创 建 者:     
*   创建日期:2022年08月03日
*   描    述:
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    int arr[10]={1,22,3,44,5,66,7,88,9,10};
    int x,i=10;
    printf("请输入要查找的值\n");
    scanf("%d",&x);
    while(i--)//从后往前遍历,循环的判定条件要比循环体多执行一次
    {
           if(arr[i]==x)
           {
                break;
           }
           
    }
    
    if(i==-1)
    {
        printf("%d没找到\n",x);
        return -1;
    }
    printf("%d的下标为%d\n",x,i);
    return 0;
} 

1.2折半查找

折半查找是针对有序的数列,简单来说就是把数据分成左右两部分,在判断要查找的值在哪一部分,之后再递归的分半查找,直到找到。

定义三个变量,low,high,mid,low保存0的下标,high保存最后一个元素的下标,mid=(low+high)/2,然后循环判断,如果要查找的值x<arr[mid],就说明在mid的左边部分,high=mid-1,mid=(low+high)/2,x>arr[mid],就说明x在mid的右边,low=mid+1,mid=(low+high)/2。继续查找。

/*===============================================
*   文件名称:zhebanchazhao.c
*   创 建 者:     
*   创建日期:2022年08月03日
*   描    述:
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    int arr[20]={};
    int i,low,high,mid,x=8;//x表示要查找的值
    for(i=0;i<20;i++)//循环赋值
    {
        arr[i]=i;
    }
    low=0;
    high=19;
    while(low<=high)//循环查找
    {
        mid=(low+high)/2;
        if(arr[mid]==x) printf("\n下标为%d\n", mid);
        if(arr[mid]>x)  high=mid-1;
        else    
            low=mid+1;
    }
    return 0;
} 

1.3分块查找

分块查找也就是把有序的数据分块,建立一张索引表,然后每块用块中最大的元素来表示。然后通过遍历索引表来确定所找的值在哪一块中,再去该块中查找元素。

1.4Hash查找

建立一张Hash表(元素下表与Key值之间的某种关联相关的一张表)

需要解决的问题:

1.建立关联

2.解决冲突(多个k值指向一个Hash地址)

选取Hash函数时应尽量减少冲突,α=n/m,(0.7~0.8),n表示记录个数,m是新的表长,自己定一个α,确定m的值

构造Hash函数的方法:

直接地址法:H(key)=a*key+b

平方取中法:b把key值平方,取中间的某三位做Hash地址。

叠加法:把key值,每一位平方(自己选),相加,再加一个特定的值,作为Hash地址。

保留除数法:新的表长m,选一个小于m的最大质数p,H(key)=key%p

                

随机函数法:H(key)=rand()%key+1;利用key通过随机数函数生成Hash地址

开放地址法:

线性探查法:Hi=(H(key)+di)%m di=1,2,3,...m

二次探查法:

di=1^2,-1^2,2^2,-2^2...(前后的空余空间都能找到)

链地址法:建立一个结构体指针数组,然后每个数组元素当做一个表头,冲突的元素就给添加在链表的后面。

/*===============================================
*   文件名称:hash.c
*   创 建 者:     
*   创建日期:2022年08月03日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>

typedef struct hash
{
    int data;
    struct hash *next;
}Hash;


void Hash_my(int *a,Hash *s[],int n)//存
{
    int i,m;
    for(i=0;i<n;i++)
    {
        m=a[i]%11;		//下标
        while(s[m]!=NULL)
        {
           s[m]=s[m]->next;
        }
     	s[m]=(Hash *)malloc(sizeof(Hash));   
        s[m]->data=a[i];
        s[m]->next=NULL;
    }
}

void Find(Hash *s[],int x)	//找
{
    int m=x%11;

    if(s[m]!=NULL)
    {
    
        while(s[m]->data!=x)
        {
           s[m]=s[m]->next;
           if(s[m]==NULL)
           break;
        }
       
        if(s[m]!=NULL)
        printf("%d",s[x%11]->data); 
        else
    	{
    		printf("\n没找到%d\n",x);
    	}
    }
    else
    {
    	printf("没找到%d",x);
    }
}

int main(int argc, char *argv[])
{ 
    int arr[10]={112,45,78,6,2,3,32,552,55,68},i,m;
    Hash *buf[13];
    for(i=0;i<13;i++)
    {
        buf[i]=NULL;
    }
    printf("请输入要查找的值\n");
    scanf("%d",&m);
    Hash_my(arr,buf,10);//创建Hash表
    
    Find(buf,m);//查找32
    puts("");
    return 0;
} 

2.排序

常用的排序方法

冒泡排序、选择排序、插入排序、快速排序

2.1冒泡排序

冒泡排序:两两交换,一轮找出一个最大值,进行N-1轮,每轮比较0~n-i-1;(最值在最后一个)

/*===============================================
*   文件名称:maopaopaixu.c
*   创 建 者:     
*   创建日期:2022年08月03日
*   描    述:
================================================*/
#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
{ 
    int arr[10]={0};
    int i,j,c;
    srand(((unsigned)time(NULL)));//调用时间函数生成随机数种子
    for(i=0;i<10;i++)    //生成随机数
    {
        arr[i]=rand()%20;
    }

    for(i=0;i<9;i++)//循环N-1次
    {
        for(j=0;j<10-i-1;j++)//每次比较前面10-1-i个数
        {
            if(arr[j]>arr[j+1])//如果比后一个大,那就交换
            {
                c=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=c;
            }
        }
    }

    for(i=0;i<10;i++)//打印
    {
        printf("%3d",arr[i]);
    }
    printf("\n");
    return 0;
} 

2.2选择排序

假设第一个最大,记录第一个变量的下标,循环一轮找到最大数的下标,判断最值的下标是否改变,如改变,与第一个交换,从第下一个开始下一次循环,循环N-1轮,从i~n(最值在开头)

/*===============================================
*   文件名称:maopaopaixu.c
*   创 建 者:     
*   创建日期:2022年08月03日
*   描    述:
================================================*/
#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
{ 
    int arr[10]={0};
    int i,j,c,k;
    srand(((unsigned)time(NULL)));//调用时间函数生成随机数的种子
    for(i=0;i<10;i++)
    {
        arr[i]=rand()%20;//生成随机数给数组赋值
    }

    for(i=0;i<9;i++)//循环N-1次
    {
        k=i;
        for(j=i+1;j<10;j++)//每次比较后面的数
        {
            if(arr[j] < arr[k])//如果arr[k]不是最值
            {
                k=j;    //记录最值的下标
            }
        }
        if(k!=i)//最值产生了变换
        {

                c=arr[i];
                arr[i]=arr[k];
                arr[k]=c;
        }
    }

    for(i=0;i<10;i++)//打印
    {
        printf("%3d",arr[i]);
    }
    printf("\n");
    return 0;
} 

2.3插入排序

2.3.1直接插入排序

把元素分为两部分,有序和无序,把无序的数据插入到有序的数据里,有序一开始为第一个元素,每次从有序的数据的下一个,也就是无序数据的第一个开始排序。

/*===============================================
*   文件名称:charupaixu.c
*   创 建 者:     
*   创建日期:2022年08月03日
*   描    述:
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    int arr[10]={1,22,3,44,5,66,7,88,9,100};
    int i,j,tmp;		
    for(i=1;i<10;i++)	//i控制总的循环次数
    {
        tmp=arr[i];	//tmp保存要插入的元素
        j=i;		//j实现一次的插入
        while(j)
        {
            if(tmp<arr[j-1])//如果tmp比前一位小,元素后移
            {
                arr[j]=arr[j-1];
            }
            else
            {
                break;		//找到合适tmp的位置
            }
            j--;
        }
        arr[j]=tmp;	//把tmp插入有序数据中
    }
    for(i=0;i<10;i++)	//打印
    {
        printf("%4d",arr[i]);
    }
    puts("");

    return 0;
} 

2.3.2希尔排序

增量,数组长度/2,每两个分为一组。x和x+d为一组。每组内部进行插入排序。

d=d/2,再分组,在插入排序,循环

直到d=1时,所有元素为一组,直接排序

d=0时,退出循环。

/*===============================================
 *   文件名称:charupaixu.c
 *   创 建 者:     
 *   创建日期:2022年08月03日
 *   描    述:
 ================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    int arr[10]={1,22,3,44,5,66,7,88,9,100};
    int i,j,tmp,d=10/2;
    for(d=10/2;d>0;d=d/2)//控制总的循环次数
    {
        for(i=d;i<10;i++)//控制每组的排序
        {
            tmp=arr[i];
            
            for(j=i-d;j>=0;j=j-d)//控制一组内的排序
            {
                if(tmp<arr[j])
                {
                    arr[j+d]=arr[j];
                }
                else
                {
                    break;
                }
                j;
            }
            arr[j+d]=tmp;
        }
    }
    for(i=0;i<10;i++)
    {
        printf("%4d",arr[i]);
    }
    puts("");

    return 0;
} 

2.4快速排序

原理:选一个基准点,排序,基准点左边的元素比他小,右边的元素比他大

定义两个变量i,j,ii指向头,j指向尾,i表示比基准小的,j表示比及基准大的。

当j的值小于基准,arr[i]=arr[j],不小于时        j--

当i的值大于基准,arr[j]=arr[i],不大于时        i++

直到 i=j 时比较完成,把基准赋给arr[i]

/*===============================================
*   文件名称:kuaisupaixu.c
*   创 建 者:     
*   创建日期:2022年08月03日
*   描    述:
================================================*/
#include <stdio.h>
#include <time.h>

void Fast_Sort(int *arr,int left,int right)
{
	if(left>=right)//后续递归的结束条件
	{
		return;
	}
	int i=left,j=right;	//保存right与left的值
	int tmp=arr[left];	//选择arr[0],作为基准
	while(i<j)		//i=j时排序完成
	{
		while(i<j && arr[j]>=tmp)	//基准从i开始,先比较j的元素
		{
			j--;
		}
		arr[i]=arr[j];			//找到比基准小,但是在基准右边的值
		
		while(i<j && arr[i]<=tmp)	//j找到一个,i也要找一个
		{
			i++;
		}
		arr[j]=arr[i];			//找到比基准大,但是在基准左边的值
	}
	arr[i]=tmp;		//把基准付给中间的值			
	
	Fast_Sort(arr,left,i-1);//递归调用,排序左边的数据
	Fast_Sort(arr,i+1,right);//递归调用,排序右边的数据
}

int main(int argc, char *argv[])
{ 
	int arr[10]={0};
	int left=0,right=9,i;
	
	srand(((unsigned)time(NULL)));
	for(i=0;i<10;i++)	//生成随机数赋初值
	{
		arr[i]=rand()%20;
	}
	
	Fast_Sort(arr,left,right);
	for(i=0;i<10;i++)	//打印
	{
		printf("%3d",arr[i]);
	}	
	puts("");

    return 0;
} 

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值