前言
这是一个C++排序算法帖,会发一些自己学的排序算法,以及对它们的理解。
一、冒泡排序
优缺点:
优点:比较简单,空间复杂度较低,是稳定的
缺点:时间复杂度太高,效率不好
1,原理解释
本例以排序int arr[10]={8,3,55,7,5,4,17,21,2,10};
为例,且按升序排序,数据在定义时给出。
冒泡排序的原理是,一个数从底下向上,如果下一个数比这个数大,就交换他们的值,保存大的值继续向上,这样最后的位置就变为了,这些数的最大数。
就像是水里的气泡,从底下不断向上升,最后升到水面。(私以为这就是冒泡排序的名字由来)
2,代码演示
#include <iostream>
using namespace std;
/*冒泡排序*/
int main()
{
int arr[10]={8,3,55,7,5,4,17,21,2,10};
int temp;//定义中间值
for(int i=0;i<9;i++) {//外层for控制输出了几个排序好的数
for(int j=0;j<9-i;j++){//内层for控制寻找这个排序的数
//每次完成一次内层for的循环,最上面就排好了一个数,所以不用循环到9个数,循环到9-i即可
if(arr[j]>arr[j+1]){//如果这个数大于下一个数,就交换它两的值
temp=arr[j];//存下将要交换数的值
arr[j]=arr[j+1];//交换这个值
arr[j+1]=temp;//现在,后一个数就是这俩个数的大值
}
}
}
for(int i=0;i<10;i++){//打印冒泡排序后的结果
cout<<arr[i]<<" ";
}
return 0;
}
结果演示:
关于为什么定义一个中间值temp:
假设我们定义了a,b。想要交换他们的值
int a=3,b=5;
我们直接赋值:
a=b;
b=a;
是无法达到交换两值的目的的,因为第二赋值值时,a的值已经被换成5了.
所以我们要定义一个中间值,先存下要被换的值。
int a=3,b=5,temp;
temp=a;
a=b;
b=temp;
这样就达到了交换的目的.
二、选择排序
优点:移动数据的次数已知(n-1 次 ),用着简单;
缺点:比较次数多。
1,原理解释
本例以排序int arr[10]={8,3,55,7,5,4,17,21,2,10};
为例,且按升序排序,数据在定义时给出。
选择排序就是从第一个数开始,比较后面的所有数,如果后面的数有小于这个数的,就将他们交换。比较完一次所有的数后就找到了其中最小的一个数,放在最前面。
所以需要两层for循环,外层for控制现在是第几个数,内层for控制这个数和其后所有数比较.
2,代码实现
#include <iostream>
using namespace std;
/*选择排序*/
int main()
{
int arr[10]={8,3,55,7,5,4,17,21,2,10};
for(int i=0;i<9;i++){//内层for会比较其后一个数,所以循环到9就可以了
for(int j=i+1;j<10;j++){//比较这个数和后面的所有数,所以要比较到9+1
if(arr[i]>arr[j]) {//如果这个数大于后面的数,就交换他们的值
int temp;//定义一个中间值
temp=arr[i];//存下被交换的值
arr[i]=arr[j];//交换这个值
arr[j]=temp; //现在它们已经交换完毕了
}
}
}
for(int i=0;i<10;i++){//打印排好顺序的数组
cout<<arr[i]<<" ";
}
return 0;
}
结果演示:
三、折半查找
1,原理解释
本例以输入一个10长的数组int arr[10]={1,5,6,8,9,12,15,17,18,20};
输入一个数num
,查找num
在这个数组的位置。
原理:为查找位置的数组设置左右边界,左边界m
,右边界n
,比较两者中间的数arr[(m+n)/2]
,看num
是在中间数的左边还是右边,移动边界,循环执行,直到找到这个数。该数是边界的数时为特殊情况,要提前判断。
简而言之就是在一半的左边还是右边,一半的一半的左边还是右边,一半的一半的一半。。。继续这样来查找
2,代码实现
本例是以输入一个数num
查找该数在数组int arr[10]={1,5,6,8,9,12,15,17,18,20};
中的位置
代码:
#include<iostream>
#include<string>
using namespace std;
/*
折半查找
输入一个数,查找它是这个10长数组的第几个元素
*/
int main() {
int arr[10]={1,5,6,8,9,12,15,17,18,20} ;
int m=0,n=9;//左边界:m,右边界:n
int num;//需要查找的数
cin>>num;//输入这个数
for(;;){
if (num>20||num<1){ //如果这个数不在该数列中,退出循环,输出错误
cout<<"输入错误"<<endl;
break;
}
if(num==arr[m]){ //当这个数是左边界时
cout<<"这个数在位置:"<<m<<endl;
break;
}
if(num==arr[n]){//当这个数是右边界时
cout<<"这个数在位置:"<<n<<endl;
break;
}
if(num<arr[(m+n)/2]){ //中间数大于这个数,移动右边界数到它们中间的位置,也就是位置:(m+n)/2
n=(m+n)/2;
}
else if(num>arr[(m+n)/2]){//中间数小于输入数时,移动左边界
m=(m+n)/2;
}
else {
cout<<"这个数在位置"<<(m+n)/2; //当中间数不大于,不小于输入数时,输入数就是现在这个中间数,输出该位置
break;
}
}
return 0;
}
代码运行结果:
输入12,找出该数在arr数组的5位置