目录
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;
}