前言
本篇文章共讲述五个排序算法与两个查找算法,其中包括了算法思想与实现代码等等…
请大家耐心观看,感谢!!!
排序算法
排序是计算机程序设计中一个非常重要的操作,它将一个数据元素的任意序列重新排列成一个按关键字有序的序列。在有序的序列中查找元素的效率很高。
这就谈到效率问题,那么时间复杂度正是反应这一问题最直观的结果,如下图:

冒泡排序
首先我们需要定义外层循环,目的是为了控制循环比较的次数,也就是说一共需要排序几次,然后再定义内部循环,而它的目的则是为了控制比较元素的个数,即比较次数。
思想:将相邻两个元素相互比较,并按照关键字排成有序序列。

具体实现代码如下:
void bubbleSort(int arr[], int length){
//这里 i<length-1 是为了能够减少循环次数,因为提取1个数据与其余剩下9个数据做对比,如果还比较10次话 会浪费时间,无形中增加了时间复杂度。
for(int i=0; i<length-1; i++){
//这里 j<length-i-1 用来控制比较值的个数
for(int j=0; j<length-i-1; j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}选择排序
待排序元素 一步一步与 其之后的元素进行比较,若满足判断则进行交换,若一直为满足判断则一直走到最后。
思想:找 最大 或 最小 的元素,往前放,分成 "已排序" 和 "待排序" 序列。

具体实现代码如下:
void selectSort(int arr[], int length){
int i, j ,temp, min;
for(i=0 ; i< length ; i++){
min = i; //min 标记 未排序第一个元素的位置
for(j=i+1; j< length ; j++){ //找 比 min位置 还小的元素
if(arr[j] < arr[min]){
min=j;
}
}
if(min != i){
temp = arr[min];
arr[min] = arr[i];
arr[i] = temp;
}
}
}插入排序
又名"直接插入排序",直接插入排序,是在有序基础上,速度最快且最稳定的排序方法。
思想:由后向前 查找 确定的位置,并插入元素。

具体实现代码如下:
void insertSort(int arr, int length){
int i, j, temp;
for( i=1; i < length ; 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; // 插入 比较的后一位
}
}希尔排序
希尔排序是由插入排序升级而来,又称 "缩小增量排序"。把直接插入方法分成插入步长由大到小不同的若干趟来进行,一开始步长较大,相当于把序列分成几个子表。对每个子表来说,因为其结点少,直接插入排序的效率会很高。以后各趟逐步减少步长,子表的结点也越来越多,但是子表中的结点已经进行过前一趟的大步长的直接插入排序,有相当多的结点已基本有序。这使得后一趟的插入排序能充分利用前一趟的排序结果。当步长降到1时,只要对基本有序的线性表进行一趟直接插入排序即可。
思想:按照 步长 进行分组,然后每一组的 第 几个 元素 进行排序。

按照上述方法排序后结果为:

具体实现代码如下:
// dk我们这里用作步长
void shellSort(int arr[],int length,int dk){
int d[3] = {5,2,1}; //定义步长
for(i=0;i<3;i++){ //这里为步长的循环
dk=t[i]; //使dk接收步长值,即第i+1个元素为第二模块
for(j=i-dk;j<length;j++){ //这里i-dk是第一模块的起始位置
//判断 每个模块的 第几个元素大小
if(arr[j]<arr[j-dk]){ //后面模块 小于 前面模块
temp=arr[j];
for(k=j-dk;k>=0 && arr[k]>temp;k-=dk){
arr[k+dk]=arr[k]; //将前面的值 给到 后面
}
arr[k+dk] = temp;
}
}
}
}快速排序
思想:定义基准值,头部从前向后找,比基准值大的元素,尾部从后向前找,找比基准值小的元素。
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

具体实现代码如下:
int getPivot(int arr[], 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;
}
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[]={4,2,7,5,9};
quickSort( arr, 0, sizeof(arr)/sizeof(int)-1 ); //这里因为需要传参值是尾部下标所以减一
}查找算法
时间复杂度:
算法名称 | 时间复杂度 | 前提条件 |
顺序查找 | O(n) | // |
二分查找 | O(logn) | 有序数组 |
顺序查找
思想:通过遍历数组一步步进行比较。
void find(int arr[], int length){
int value;
printf("请输入待查找数据");
scanf("%d",&value);
for(int i=0; i<length ;i++){
if(arr[i] == value){
printf("%d存在数组中,其下标为:%d",value, i);
}
}
}二分查找
二分查找 又名 "折半查找",通过取中间值对其中一半进行查找,该查找还可分为递归与非递归两种写法。
思想:查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。
具体实现代码如下:
//非递归编写方法
int binarySearch(int arr[], int low, int high, int key){ //low 左值, high 右值, key 待查找数据
int mid; //定义中间值下标
while( low <= high ){
mid = (low+high)/2; //计算中间值下标
if( key == arr[mid] ){
return mid; //返回下标
} else if( key > arr[mid] ){
low = mid + 1; //key 大于中间值,头移动至中间值后一位
} else {
high = low - 1; //key 小于中间值,尾移动至中间值前一位
}
}
//没有找到待查找数据
return -1;
}//递归编写方法,思想同上
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); //这里重新调用了该函数,将头部参数改变为中间值的后一位
}else {
return binarySearch(arr, low, mid-1); //这里也是重新调用了该函数,将尾部参数改变为中间值的前一位
}
}
//未找到该数据
return -1;
}本篇文章草草结束啦,希望大家喜欢~~


766

被折叠的 条评论
为什么被折叠?



