C++学习之排序、查找算法

一、算法:
    1、数据结构中的算法,指的是数据结构所具备的功能,解决问题的方法,它是前辈们的一些优秀的经验总结
    2、算法有五大特征:可行性、有穷性、确定性、输入、输出
    3、如何评价一个算法:
        1.时间复杂度:由于计算机性能的不同,无法准确地统计出一个算法执行所需要的时间,
                     因此采用算法的执行次数来代表算法的时间复杂度
                     一般采用O(公式),公式里忽略常数,n
        2.常见的时间复杂度:
            O(1): printf("%d",i);
            O(logn):log以2为底,折半
                for(int i=n;i>=0;i/=2) 
                            {
                                printf("%d",i);
                            }
            O(n): 
                for(int i=0;i<n;i++)
                    {
                        printf("%d",i);
                    }
            O(nlogn)
                for(int i=0;i<n;i++)
                {
                    for(int j=n;j>0;j/=2)
                    {
                        printf("%d",i);
                    }
                }
            O(n^2)
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<n;j++)
                    {
                        printf("%d",i);
                    }
                }
        3.空间复杂度:执行一个程序所需要的额外的内存空间大小,是对一个算法在运行过程中 额外 临时占用的空间大小的一个度量
                     通常来说,只要算法不涉及动态分配的空间(堆内存)以及递归、基本上空间复杂度O(1),涉及到了是O(n)
二、算法类型
    1、分治:分而治之
        把一个大而复杂的问题,分解成若干个小而简单的问题,利用计算机强大的计算能力来解决所有的小问题,是一种算法思想
        实现分治思想的方法:循环、递归
    2、查找:
        1.顺序查找:对待查找的数据没有要求,从头到尾逐一比较,适合在小规模的数据查找中比较常见,相比较而言效率较低
        时间复杂度:O(n)
        2.二分查找:折半查找,待查找的数据必须有序,从中间位置数据开始比较查找,如果中间值比待查找值小,
                   则左部分进行查找,反之从右部分二分查找,如果相同则查找成功,当查找的范围缩小为0则查找失败
        3.块查找:是一种数据查找处理的思想,不是特定能实现的算法,当数据量过多时,可以把数据进行特定的分块处理,然后
                 再进行查找,例如单词字典
        4.哈希查找:Hash
            数据先经过哈希函数就算出该数据在哈希表中的位置,然后标记该位置的数据,之后查找数据直接从哈希表中查找
            它的查找时间复杂度最快能到O(1)
            局限性:不适合浮点型、字符型数据,有符号负数数据,还需要额外的内存空间,空间复杂度高,
            还不好确定额外的空间大小,c一种典型的空间换时间的算法

            设计哈希函数的常见方法:
                1.直接定址法:把数据当做哈希表的下标来标记哈希表
                2.数据分析法:先分析数据的特点,然后设计哈希函数,常用方法是先找出最大最小值,
                  哈希表长度:最大值-最小值+1
                  哈希函数:数据-最小值,作为哈希表下标进行标记
                3.平方折中法、折叠法、随机数法等方法设计哈希函数
                如果出现相同数据时,哈希表会出现所谓的哈希冲突,一般使用链表解决
        
    哈希函数应用:MD5、SHA-1都属于哈希算法
        5.排序算法:
            排序算法的稳定性:带排序数据中,如果存在值相同的数据,如果在排序的过程中不会改变他们前后顺序,则认为排序算法是稳定的
            
            冒泡:数据左右相比,把大的数据交换到右边,然后继续下两个数据左右相比,直到最大的数据交换到末尾,重复以上步骤
            注意:在冒泡排序中一旦发现数据已经有序,立即停止排序,称为有序性敏感
            冒泡排序适合数据基本有序的情况下,冒泡效率非常高
            时间复杂度:最好O(n) 平均:O(n^2)
            稳定性:稳定
            #include <stdio.h>
            #include <string.h>
            #include <stdbool.h>
            #include <stdlib.h>

            #define LEN 15
            #define TYPE int

            #define show_arr(arr,len) {
                for(int i=0;i<len;printf("%d ",arr[i++]));}
            #define swap(a,b) {typeof(a) t=(a);(a)=(b);(b)=t;}

            typedef void (*SortFP)(TYPE* arr,size_t len);

            //    冒泡
            void bubble_sort(TYPE* arr,size_t len)
            {
                bool flag = true;    //解决有序性敏感
                for(int i=len-1; i>0 && flag; i--)
                {
                    flag = false;
                    for(int j=0; j<i; j++)
                    {
                        if(arr[j] > arr[j+1])
                        {
                            swap(arr[j],arr[j+1]);    
                            flag = true;
                        }
                    }
                }
                show_arr(arr,len);
                printf(" %s\n",__func__);
            }
           
            选择:假定最开始的位置是最小值并记录下标min,然后与后面的数据进行比较,如果有
            比min为下标更小的值,则更新min,如果比较结束后,min的位置发生了改变,则交换最开始的位置与min的值
            虽然时间复杂度没有变化,但是交换次数比较少,因此实际的运行速度并不慢(数据交换要比赋值,数据比较耗时)
            选择排序相当于冒泡排序的一种变种,但是不存在有序性敏感,比较适合数据比较混乱的情况会比冒泡块
            时间复杂度:O(n^2)
            稳定性:不稳定
                    10  10  1
                    a    b  

            插入:把数据看成两部分,一部分是有序的,后一部分的数据与有序部分的数据逐个比较,直到找到合适的位置后插入到该位置
                  适合对已排序的数据新增数据后进行排序
            时间复杂度:O(n^2)
            稳定性:稳定

            希尔:是插入排序的一个增强版,由于插入排序数据移动的速度比较慢,如果待排序数据很混乱是效率较低,因此引入增量的概念
                 数据间隔增量个数进行插入排序,然后不停地缩小一杯=倍增量,直到增量为1,此时数据从很混乱变为接近有序,以此提高排序效率
                 时间复杂度:O(nlogn)
                 稳定性:不稳定

            快速(快排):在中间位置确定为一个标杆,备份备份标杆的数据val,在左边找比val大的数据,找到后位置为1,
                       然后把该数据赋值给p位置,更新p为l

            注意:快排的综合性能是所有综合性能中最高的,也是笔试最常考的一种排序算法
            时间复杂度:O(nlogn)
            稳定性:不稳定

            归并:先将数据拆分成单独的个体,然后再按照从小到大的顺序把两组数据合并到临时空间中,
                 合并结束后,再重新拷贝回原空间的原位置中,得到数量翻倍的一组组有序的数据,继续两组两组合并,直到整体有序为止
                 归并排序是利用了额外的内存空间,避免了数据交换的耗时,是一种典型的以空间换时间的算法
                 时间复杂度:O(nlogn)
                 稳定性:稳定

            堆:先把数据看成一棵完全二叉树,然后先调整成大顶堆或小顶堆,然后把根节点与末尾交换,然后有效个数-1,
                重新调整成堆结构,继续以上步骤,直到有效个数为1,此时整个数组就有序了,既可以循环实现,也可以递归实现
                大顶堆:堆排序后,从小到大
                小顶堆:堆排序后,从大到小
                时间复杂度:O(nlogn)
                稳定度:不稳定  例如:1  10  10

            计数:在数据中找出最大值和最小值,通过最大值-最小值方式建立哈希表,然后根据 数据-最小值 的值作为哈希表的下标,
                  访问并标记(累加)对应的哈希表标记所有数据,排序时遍历整个哈希表,如果表中数据非零时,把该位置下标+最小值
                  依次存回排序数组中,遍历结束,数组有序,理论上计数排序非常快,因为它不是基于比较的排序,在一定范围内整数
                  排序时快于任何一种比较排序算法,但是有很大的局限性,适合无符号整型,正整型数据,并且数据的差值不宜过大
                  ,否则会非常浪费内存,因此,如果数据越平均,重复数据多的情况下,该排序性价比越高。空间换时间
                  时间复杂度:O(n+k),k是待排序的整数的范围
                  注意:如果k范围过大,效率可能会低于O(nlogn)
                  稳定性:稳定
            桶:根据数据的值,存储到不同的桶中,然后调用其他的排序算法对桶中的数据进行排序,然后再全部按桶的顺序拷贝回数组中
                以此降低排序的规模来提高排序速度,以空间换时间的算法
                缺点:如何分桶、桶有几个、桶定义多大都不一定,需要对排序数据有一定的了解和分析后才能确定
                时间复杂度:O(n)
                稳定性:稳定

            基数:是桶排序思想的其中一种具体实现,首先会创建10个队列(10个桶),然后依次按照数据的个、十、百…位的顺序,入队
            到对应的桶中,然后依次每个桶出队回原来的数组中,当最高位都处理完且返回数组后,数组就有序
            缺点:只适合排序正整数数据,需要准备大量的临时空间
            时间复杂度:O( )
            稳定性:稳定
            313 827 12 937 82 2 6 1751 3330 36 1
        0    
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10

总结10种排序算法:
    排序 最优 最差 平均 空间复杂度 稳定性 特点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值