算法总结

递归

一个过程或函数在其定义中有直接或间接调用自身的一种方法

优点:

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)

平均: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)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值