递归
一个过程或函数在其定义中有直接或间接调用自身的一种方法
优点:
1.减少解决问题所需要的重复性代码,代码更简洁清晰,
2.易于理解
缺点:
1.递归需要多次函数调用, 运行效率较低
2.递归调用需要大量的栈空间,容易造成栈溢出
使用:
递归算法一般用于解决三类问题:
1.数据的定义是按递归定义的。(Fibonacci函数)
2.问题解法按递归算法实现。(回溯)
3.数据的结构形式是按递归定义的。(树的遍历,图的搜索)
排序算法
稳定和非稳定算法:如果链表中存在两个相同元素,稳定排序算法可以在排序之后保持他两原来的次序,而非稳定性的则不能保证
简单排序算法
插入排序
在已经有序的数据序列中插入一个数,得到新的有序序列
流程:
代码(c语言):
void insertion_sort(int *arr, int n)
{
int i, j, tmp;
for(i = 1; i < n; ++i){//从第一个无序数据开始
tmp = arr[i]; //保存进行对比的元素
for(j = i; j > 0 && tmp < arr[j - 1]; --j){//与前一个数据比较,一直循环到数组头
arr[j] = arr[j - 1];//如果前一个元素较大,则前一个元素后移
}
arr[j] = tmp;//插入当前位置
}
}
时间复杂度:
最好:已经排好顺序的集合,这样只需要线性时间即遍历一次集合,每次只需要比较当前元素与前一个元素的大小问题,O(n)
最坏:即刚好与所要的顺序相反,为O(n^2)
平均:O(n^2)
选择排序
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完
流程:
代码:
void selection_sort(int *arr, int n)
{
int i, j, min, tmp;
for(i = 0; i < n - 1; ++i){
min = i;
for(j = i + 1; j < n; ++j){//从未排序元素查找最小值
if(arr[j] < arr[min])
min = j;
}
if(min != i){//交换最小值
tmp = arr[min];
arr[min] = arr[i];
arr[i] = tmp;
}
}
}
时间复杂度:
最好:O(n^2)
最差:O(n^2)
平均:O(n^2)
归并排序
将两个已经排序的序列合并成一个有序序列的操作
流程:
代码:
void merge(int *arr1, int n1, int *arr2, int n2)
{
int i = 0, j = 0, k = 0;
int tmp[n1 + n2];
while(i < n1 && j < n2){//归并有序序列到临时序列
tmp[k++] = arr1[i] < arr2[j] ? arr1[i++] : arr2[j++];
}
while(i < n1)//复制剩余的数据
tmp[k++] = arr1[i++];
while(j < n2)//复制剩余的数据
tmp[k++] = arr2[j++];
for(i = 0; i < n1 + n2; ++i)//将结果写回数组
arr1[i] = tmp[i];
}
void merge_sort(int *arr, int n)
{
if(n > 1){//直到元素个数为1
int *arr1 = arr;//从中间分,分成两个子序列
int n1 = n / 2;
int *arr2 = arr + n1;
int n2 = n - n1;
merge_sort(arr1, n1);//分别对子序列进行归并排序
merge_sort(arr2, n2);
merge(arr1, n1, arr2, n2);//合并两个子序列
}
}
时间复杂度:
最好:O(n log n)
平均:O(n log n)
快速排序
将数据分成两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
流程:
代码:
void quick_sort(int *arr, int n)
{
int i = 0, j = n - 1, p = arr[i];//p为基准的值
if(n > 1){//递归边界条件
while(i < j){
for(; i < j; j--){//从后到前,移动一个比基准小的数到前面
if(arr[j] < p){
arr[i] = arr[j];
break;
}
}
for(; i < j; i++){//从前到后,移动一个比基准大的数到后面
if(arr[i] > p){
arr[j] = arr[i];
break;
}
}
}
arr[i] = p;//插入正确位置,此时前面所有数都比基准小,后面所有数都比基准大
quick_sort(arr, i);//对前部分进行快速排序
quick_sort(arr + i + 1, n - i -1);//对后面部分进行快速排序
}
}
时间复杂度:
最优:O(n log n)
最差:O(n^2)
平均:O(n log n)