我们所学到的顺序表(也就是数组),可以对其进行很多操作,比如排序和查找,我们今天就来学习排序和查找


一:排序:
一:冒泡排序(思想:两数比较,将最大或者最小的元素,放到最后 i 循环时控制元素比较多少趟的,内层循环j是来控制元素一趟的比较次数,两数相邻的比较,每一轮都能找出一个最大值或者最小值放到最后)

代码实现如下:
void bubbSort(int arr[],int len){
int i,j,temp; //定义外层循环变量i 内层循环变量j 临时变量temp
for(i=0;i<len-1;i++){ // 外层控制元素比较多少趟
for(j=0;j<len-i-1;j++){ //内层控制元素一趟比较的次数
if(arr[j]>arr[j+1]){ //从小到大进行排序
temp=arr[j];
arr[j]=a[j+1];
arr[j+1]=temp;
}
}
}
}
int main(){
int arr[10];
int i;
for(i=0;i<10;i++){
printf("请输入第%d个元素:",(i+1));
scanf("%d",&arr[i]);
}
bubbSort(arr,10);
for(i=0;i<10;i++){
printf("%d ",arr[i]);
}
}
二:简单选择排序(思想:找最大或者最小的元素往前放,分成已排序序列和待排序序列,第一次从待排序序列中找到一个最大值或者最小值放到序列开始位置,定义一个变量min是来存储最小值的下标 j循环是从i的下一位开始的,去找比min还要小/大的元素)

代码实现如下:
void selectSort(int arr[],int len){
int i,j,t,min;
for(i=0;i<len;i++){
min=i; //min标记未排序第一个元素的位置
for(j=i+1;j<len;j++){ //找比min还小的元素
if(arr[min]>arr[j]){
min=j
}
}
if(min!=i){ //如果最小值所在位置不为i,交换最小值和第i个元素的位置
t=arr[min];
arr[min]=arr[i];
arr[i]=t;
}
}
}
int main(){
int arr[10];
int i;
for(i=0;i<10;i++){
printf("请输入第%d个元素:",(i+1));
scanf("%d",&arr[i]);
}
selectSort(arr,10);
for(i=0;i<10;i++){
printf("%d ",arr[i]);
}
}
三:直接插入排序(把第一个数理解为有序的,直接插入排序i下标的位置是从1开始的,然后定义一个临时变量temp,将当前i下标位置的数据暂存放到temp,j的循环是从i的前一位开始的,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。将后面的每个数,依次往前移动,直到找到它恰好能放的位置。)

代码实现如下:
//直接插入排序
int insert (int arr[],int len){
int i,j,temp;
for(i=1;i<len;i++){
temp=arr[i];
for(j=i-1;j>=0 && arr[j]>temp ;j--){
arr[j+1]=arr[j];
}
arr[j+1]=temp;
}
}
int main(){
int arr[10];
int i;
for(i=0;i<10;i++){
printf("请输入第%d个元素:",(i+1));
scanf("%d",&arr[i]);
}
insert(arr,10);
for(i=0;i<10;i++){
printf("%d ",arr[i]);
}
}
四:希尔排序(在上面我们学习了直接插入排序,而希尔排序就是对直接插入排序的改良版,称为”缩小增量“,写希尔排序我们要定义这个的步长,以下代码我定义的步长就是用dk来接受的,每次都以步长为基准,找到数据,对其进行从大到小或者从小到大排序,最后当步长到1的时候我们就可以对其所有数据排序,最终达到从大到小或者从小到大的排序)

代码实现如下:
//希尔排序
int shellSort (int arr[],int len,int dk){
int i,j,temp;
for(i=dk;i<len;i++){
if(arr[i]<arr[i-dk]){
temp=arr[i];
j=i-dk;
for(;j>=0 && arr[j]>temp;j-=dk){
arr[j+1]=arr[j];
}
arr[j+1]=temp;
}
}
}
int main(){
int arr[6];
int i;
for(i=0;i<6;i++){
printf("请输入第%d个元素:",(i+1));
scanf("%d",&arr[i]);
}
int b[2]={2,1};
int dk;
for(int k=0;k<2;k++){
dk=b[k];
}
shellSort(arr,6,dk);
for(int i=0;i<6;i++){
printf("%d ",arr[i]);
}
}
五:快速排序(快速排序需要用到递归来实现,定义一个基准值,还有low是前半部分,high是后半部分,若是想要从小到大序列,则high大于基准值就不动,high则往前走,high是找比基准值还要小的数据,当找到后就会将high位置上的数据给到low位置上,则反之low是找比基准值还大的数据,若没找到就一直往后走,若找到则将low位置的数据给到high位置,在下面的代码中我用到了分区函数来对数据进行分区)

代码实现如下:
//快速排序
int fenqu(int arr[],int len,int low,int high){
int pivot=arr[low];
while(low<high ){
while(low<high && arr[high]>pivot){
high--;
}
arr[low]=arr[high];
while(low<high && arr[low]<=pivot){
low++;
}
arr[high]=arr[low];
}
arr[low]=pivot;
return low;
}
int quickSort(int arr[],int len,int low,int high){
if(low<high){
int d=fenqu(arr,len,low,high);
//对左边进行操作
quickSort(arr,len,low,d-1);
//对右边进行操作
quickSort(arr,len,d+1,high);
}
}
int print(int arr[],int len){
for(int i=0;i<len;i++){
printf("%d ",arr[i]);
}
}
int main(){
int arr[10];
int i;
for(i=0;i<10;i++){
printf("请输入第%d个元素:",(i+1));
scanf("%d",&arr[i]);
}
int low=0,high=10-1;
quickSort(arr,10,low,high);
print(arr,10);
}
二:查找(我们常见的查找有顺序查找,二分查找,二分查找分为递归和非递归,分块查找)
一:顺序查找(顺序查找也就是遍历那个数组,然后拿要查找的数据依次比较,找到即返回下标,若没找到则返回-1)
代码实现如下:
//顺序查找
int findValue(int arr[],int len,int value){
int i;
for(i=0;i<len;i++){
if(value==arr[i]){
return i;
}
}
return -1;
}
int main(){
int arr[10]={2,1,3,5,4,6,8,7,9,10};
int value;
printf("请输入你要查找的数据:");
scanf("%d",&value);
int d=findValue(arr,10,value);
if(d==-1){
printf("查找失败,没有找到该元素");
}else{
printf("查找成功,下标为:%d",d);
}
}
二:折半查找(也成为二分查找 ,折半查找的特点就是数据必须是有序的。 折半查找分为递归和非递归,折半查找需要用到一个头(low)和尾(high),需要中间下标当输入的数据和中间位置数据相等则直接返回下标,否则看序列是从大到小还是从小到大,若是从小到大,输入的数据大于中间值时则头动尾不动)

非递归代码如下:
//二分查找 (非递归)
//arr 数组,low 左边值 high 右边值 key 要查找的关键字
int binary(int arr[],int low,int high,int key){
int mid; //中间值
while(low<=high){ //循环的终止条件是最小下标大于最大下标,即区域内 没有元素
mid=(low+high)/2; //找中间位置
if(key==arr[mid]){
return mid; //返回下标
}else if(key>arr[mid]){
low=mid+1;
}else{
high=mid-1;
}
}
//没有找到关键字
return -1;
}
int main(){
int arr[10]={2,8,10,12,15,19,23,26,29,33};
int value;
printf("请输入你要查找的数据:");
scanf("%d",&value);
int low=0,high=10-1;
int d=binary(arr,low,high,value);
if(d==-1){
printf("查找失败,没有找到该元素");
}else{
printf("查找成功,下标为:%d",d);
}
}
递归代码如下:
//二分查找 (递归)
int binary(int arr[],int low,int high,int key){
int mid; //中间下标
if(low<=high){ //循环的终止条件是最小下标大于最大下标,即区域内 没有元素
mid=(low+high)/2;
if(key==arr[mid]){
return mid; //递归出口
}else if(key>arr[mid]){
return binary(arr,mid+1,high,key);
}else{
return binary(arr,low,mid-1,key)
}
//没有找到关键字
return -1;
}
int main(){
int arr[10]={2,8,10,12,15,19,23,26,29,33};
int value;
printf("请输入你要查找的数据:");
scanf("%d",&value);
int low=0,high=10-1;
int d=binary(arr,low,high,value);
if(d==-1){
printf("查找失败,没有找到该元素");
}else{
printf("查找成功,下标为:%d",d);
}
}
三:分块查找(先将原数组分块(分块的条件是,原数组的数据必须有明确的区间,否则不能分块) ,从前往后遍历所有临界条件,找到n所在的区间 ,用顺序查找遍历目标区间,找到目标 )

代码实现如下:
//分块查找
int main(){
int a[12]={12,15,11,13,14,17,9,5,4,0,2,1};
//建立索引表(5个数为一组)
int suo[2]={11,0};
//通过索引表里面的数据,确定在第几个区间
//输入要查找的数据
int n;
printf("请输入要查找的数据:");
scanf("%d",&n);
int i,d;
//找到数据所在区间
for(i=0;i<2;i++){
if(n>=suo[i]){
break;
}
}
if(i==2){
printf("数据不在数组中!");
}
else{ //数据在区间中
//找到该区间的起始下标
int j=6*i;
int k;
for(k=0;k<6;k++){
if(n==a[j+k]){
printf("数组包含%d,其下标为:%d",n,j+k);
return 0;
}
}
printf("数组中不包括%d!",n);
}
}