排序算法是平时开发和工作中经常遇到的,今天为大家总结了五种最常用的排序算法,每一种算法都附带一张排序过程的动图,让大家更加直观的了解排序算法实现思想。
冒泡排序:
思想:
两数比较,将最大或者最小的元素,放到最后。
![](https://i-blog.csdnimg.cn/blog_migrate/a7b0cf2cbf1ca8b2be737bbb172d485f.gif)
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#define N 15 //全局变量
void kreyType(int arr[]){ //接收
int i,j,temp; //定义 外层循环变量 i 内层循环变量 j 临时变量temp
for(i=0 ; i<N-1 ; i++){ //外层 控制 元素 比较多少趟
for(j=0 ; j<N-i-1 ; j++){ //内层 控制 元素 一趟比较的次数
if(arr[j] > arr[j+1]){ //从小到大排序
trmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//输出
for(int k ; k<N ; k++){
printf("%d\t",arr[k]);
}
}
int main(){
int arr[N]; //定义数组
for(int i=0 ; i<N ; i++){ //循环变量
printf("请输入第%d个元素:",(i+1)); //提示语15个数
scanf("%d",&arr[i]); //输入数值
}
kreyType(arr); //创建子函数
}
注意:
冒泡排序稳定,最多执行n(n-1)/2次
选择排序
思想:
找最大或者最小的元素,往前放,分成 已排序和待排序序列。
![](https://i-blog.csdnimg.cn/blog_migrate/38370775063eb6f7b2137374ae65e87e.gif)
void selectSort(int arr[],int len){
int i,j,temp,min;
for(i=0;i<len;i++){
min = i; //min标记 未排序第一个元素 的位置
for(j=j+1;j<len;j++){ //找比 min 位置还小的元素
if(arr[j] < arr[min]){
min=j;
}
}
if(min!=i){
temp = arr[min];
arr[min] = arr[i];
arr[i] = temp;
}
}
//遍历排序后结果
for (int k = 0; k < 10; k++) {
printf("%d ", arr[k]);
}
}
int main(){
int arr[15]; //定义数组
for(int i=0 ; i<15 ; i++){ //循环变量
printf("请输入第%d个元素:",(i+1)); //提示语15个数
scanf("%d",&arr[i]); //输入数值
}
selectSort(arr,15);
}
注意:
选择排序不稳定, 平均比较次数n(n-1)/2
直接插入排序
思想:
从后向前进行 查找 确定位置,并插入元素
![](https://i-blog.csdnimg.cn/blog_migrate/ff12f98527eea1dc4197641e75c766cf.gif)
void insertSort(int arr[],int len){
int i,j,temp;
for(i=1;i<len;i++){ //从 1 开始, 0 位置当成有序
temp = arr[i]; //temp 记录未排序第一个
for(j=i-1;j>=0 && arr[j]>temp;j--){
arr[j+1] = arr[j]; //元素后移,腾位置给插入元素
}
arr[j+1] = temp; //插入比较的后一位
}
//遍历排序后结果
for (int k = 0; k < 10; k++) {
printf("%d ", arr[k]);
}
}
int main(){
int arr[];
for(int i=0 ; i<15 ; i++){ //循环变量
printf("请输入第%d个元素:",(i+1)); //提示语15个数
scanf("%d",&arr[i]); //输入数值
}
insertSort(arr,15);
}
注意:
直接插入排序,是在有序的基础上,速度最快且最稳定的排序方法
希尔排序
思想:
按照 步长 进行分组,然后每一组的 第 几个 元素 进行排序
增量 及 步长
![](https://i-blog.csdnimg.cn/blog_migrate/a34581150f791778b078c82ea455a25c.gif)
//dk是增量
void shellInsert(int arr[],int len,int dk){
int i,j,temp; // i 循环变量 j前边组的位置, temp 临时变量
for( i = dk; i< len; i++){
//判断每组的 第几个元素 大小
if(arr[i]<arr[i-dk]){ // 后边组 小于 前边组
temp = arr[i];
for( j = i-dk ;j>=0 && temp < arr[j] ; j = j - dk){
//前边的值 给到 后边
arr[j+dk] = arr[j];
}
arr[j+dk] = temp;
}
}
//遍历排序后结果
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main(){
int arr[10];
for(int i=0 ; i<10 ; i++){ //循环变量
printf("请输入第%d个元素:",(i+1)); //提示语10个数
scanf("%d",&arr[i]); //输入数值
}
int gap[3] = {5,2,1}; //增量表
int dk;
for(int i=0 ; i<3 ; i++){ //遍历增量表
dk = gap[i]; //获取排序增量dk
shellInsert(arr,10,dk); //按照增量dk 调用插排
}
}
希尔排序是 不稳定的
快速排序
思想:
基准值,i从前向后找,比基准值大的元素 j 从后向前找,找比基准值小的元素,最后,结束的条件 i=j 此时将 基准值放到这个位置
![](https://i-blog.csdnimg.cn/blog_migrate/3a5bb752dbd9a50e15c753df28c8063f.gif)
int getPivot(int arr[],int low,int high){
int pivot = arr[low];
while(low < high){ //i < j 的时候
// j 从后向前找,比基准值 小的元素
while(low < high && arr[high] >= pivot){
high--;
}
// 找到了比基准值小的元素 将元素 给到 i 位置
arr[low] = arr[high];
// i 从前向后找,比基准值大的元素
while(low < high && arr[low] <= pivot){
low++;
}
// 找到了比基准值大的元素 将元素 给到 i 位置
arr[high] = arr[low];
}
//结束条件 i = j 找到了基准值的位置
arr[low] = pivot
//返回基准值位置
return low;
}
void quickSort(int arr[],int low,int high){
if(low < high){
// 基准值位置的变量
int pivot = getPivot(arr,low,high);
// 递归 对 基准值位置 左边进行 快速排序
quickSort(arr,low,pivot-1);
// 递归 对 基准值位置 右边进行 快速排序
quickSort(arr,pivot+1,high);
}
}
int main(){
int arr[10];
for(int i=0 ; i<10 ; i++){ //循环变量
printf("请输入第%d个元素:",(i+1)); //提示语10个数
scanf("%d",&arr[i]); //输入数值
}
quickSort(arr,0,9);
//遍历排序后结果
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
}
顺序查找
“顺序查找是按照序列原有顺序对数组进行遍历比较查询的基本查找算法。 基本原理: 对于任意一个序列以及一个给定的元素,将给定元素与序列中元素依次比较,直到找出与给定关键字相同的元素,或者将序列中的元素与其都比较完为止。
思想:
遍历数组,拿元素依次比较,相同返回 下标,找不到,返回-1
//arr 数组 len数组长度 value 要查找的值
void linearSearch(int arr[],int len,int value){
int i;
for(i=0;i<len;i++){
if(arr[i] == value){
return i;
}
}
return -1; //找不到
}
int main(){
int i;
int arr[5];
for(i=0; i<5; i++) {
printf("请输入%d个元素:",i+1);
scanf("%d",&arr[i]);
}
int value;
printf("请输入你要查找的数:");
scanf("%d",&value);
int d=linearSearch(arr,5,value);
if(d!=-1) {
printf("该元素为%d下标为%d",value,c);
} else {
printf("没有该元素!");
}
}
二分查找(递归)
二分查找又称折半查找,是对一个有序的列表通过按中间元素切分搜索空间进行快速查找的,也可以通过递归或非递归方法实现。
int binarySearch(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 binarySearch(arr,mid+1,high,key);
}
else{
return binarySearch(arr,low,mid-1,key);
}
}
return -1;
}
int main(){
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int key;
printf("请输入你要查找的数字:");
scanf("%d",&key);
binarySearch(arr,0,9,key);
}
二分查找(非递归)
二分查找法只适用于从有序的数列中进行查找(比如数字和字母等),将数列排序后再进行查找
二分查找法的运行时间为对数时间O(log₂n) ,即查找到需要的目标位置最多只需要㏒₂n步,假设从[0,99]的队列(100个数,即n=100)中寻到目标数30,则需要查找步数为log₂100 , 即最多需要查找7次( 2^6 < 100 < 2^7)
//arr 数组,low 左边值 high 右边值,key 要查找的关键字
int binarySearch(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]={1,2,3,4,5,6,7,8,9,10};
int key;
printf("请输入你要查找的数字:");
scanf("%d",&key);
binarySearch(arr,0,9,key);
}