【数据结构】数据结构与算法知识梳理(下):算法篇

算法:
   输入: 算法具有0个或多个输入
   输出: 算法至少有1个或多个输出
   有穷性: 算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤可以在可接受的时间内完成
   确定性:算法中的每一步都有确定的含义,不会出现二义性
   可行性:算法的每一步都是可行的,也就是说每一步都能够执行有限的次数完

   如果评价一个算法:
      时间复杂度:由于计算机的性能不同,无法准确统计出算法执行所需要的时间。
         因此我们用算法执行的次数来代表算法的时间复杂度,O(公式),一般忽略常数。
      
      常见的时间复杂度:
         // O(1)
         printf("%d",i); 
         // O(logn)
         for(int i=n; i>=0; i=i/2)
         {
            printf("%d",i);
         }
         // O(n)
         for(int i=0; i<n; i++)
         {
            printf("%d",i);
         }
         // O(nlogn)
         for(int j=0; j<n; j++)
         {
            for(int i=n; i>=0; i=i/2)
            {
               printf("%d",i);
            }
         }
         // O(n^2)
         for(int i=0; i<n; i++)
         {
            for(int j=0; j<n; j++)
            {
               printf("%d",i*j);
            }
         }
算法的时间复杂度并不能代表算法的实际执行时间,有些时候看似复杂度高的速度反面快。

查找算法:
   顺序查找:
      对待查找的数据没有要求,时间复杂度: O(n)
   二分查找:
      对待查找的数据必须有序,时间复杂度: O(logn)
   块查找:
      是一种数据处理的思想,不是特定的算法,当数据量过多时,可以先把数据进行分块处理,然后再进行查找,例如英语词典。
   哈希查找:
      数据 经过哈希函数 计算出数据在哈希表中的位置,然后标记,方便之后的查找,它的时间复试度最快能达到:O(1)。
      但是该算法有很大局限性,不适合浮点型、字符串型数据,需要额外的存储空间,空间复杂度高,是一种典型的用空间换取时间的算法。

      哈希函数设计方法:
         直接定址法:把数据直接当作数组的下标。
         数字分析法:分析数据的特点来设计哈希,常用的方法就是找到最大值与最小值,最大值-最小值+1来确定哈希表的长度,数据-最小值访问哈希表。
         
排序算法:
   冒泡:数据左右进行比较,把最大的数据交换到最后,特点是该算法对数据的有序性敏感,在排序过程中可以立即发现已经完成。
      时间复杂度:O(n),O(n^2)
      稳定

   选择:假定最开始的位置是最小值并记录下标min,然后与后面的数据进行比较,如果有比以min为下标的数据小的则min的更新,最后如果min的如果发生改变,则交换min与最开始位置的数据,虽然时间复杂度挺高的,但数据交换的次数比较小,因此实际运行速度并不慢(数据交换比数据比较耗时)。
      时间复杂度:O(n^2)
      不稳定

   插入:把数据看作两部分,一分部是有序,把剩余的数据逐个插入进行,适合对已经排序后的数据,新增数据并排序。
      时间复杂度:O(n^2)
      稳定

   希尔:是插入排序的增加版,由于插入排序时,数据移动的速度比较发慢,所以增加了增量的概念,以此来提高排序速度。
      时间复杂度:O(nlogn)
      不稳定
      
   快速:找到一个标杆,一面从左找比标杆大的数据,找到后把放在标杆的右边,另一个从右边找比标杆小的数据,找到后把放在标杆的左边,最终标杆左边的数据都比它小,右边的数据都比它大,这样就整体有序,然后按同样的方法排序标杆左边的数据和标杆右边的数据。
      它的综合性能最高,因此叫快速排序,笔试时考的最多的排序。
      时间复杂度:O(nlogn)
      不稳定

   归并:先一组把数据拆分成单独的个体,然后按从小到大的顺序进行合并,由于需要使用额外的内存空间因此避免的数据交换的耗时,也是一种典型的用空间换取时间的算法,可递归实现也可以循环实现。
      时间复杂度:O(nlogn)
      稳定

   堆:把数据当作完全二叉树,然后树中调整为大根树,然后把根节点交换到最后,然后数量--,然后再调整为大根树,直到数量为1时结束,可递归实现也可以循环实现。
      时间复杂度:O(nlogn)
      不稳定

   计数:找出数据中的最大值和最小值,创建哈希表,把数据-最小值当作数组中的下标访问哈希表并标记数量,然后遍历哈希表,当表中的值大于时,把下标+最小值依次放入数组中,是一种典型的用空间换取时间的算法。
      该排序算法理论上速度非常快,但有很大局限性,适合排序整型数据,而且数据的差值不宜过大,否则会非常浪费内存,数据越平均、重复数越多,性价比越高。
      时间复杂度:O(n+k);
      稳定

   桶:把数据根据值,存储到不同桶中,然后再调用其它排序函数,对桶中的数据进行排序,然后再拷贝到数组中,以到降低排序规模来提高排序的时间,是一种典型的用空间换取时间的算法。
      时间复杂度:O(n+k);
      稳定

扫描二维码关注公众号,回复: 11702458 查看本文章

   基数:是桶排序的具体实现,首先创建10个队列(队列),然后逆序计算出数据的个十百... 然后压入到对应的队列中,然后再从队列中弹出存储的数组中,当下标为0队列中有len个数据时,排序结束。
      时间复杂度:O(n+k);
      稳定

如何判断排序算法是否稳定:
   待排序的数组中,如果有值相同的数据,排序过程中如果不会改它们的前后顺序,则认为该排序算法稳定。

排序    最优    最差    平均     空间复杂度    特点    是否稳定
冒泡    o(n)    O(n^2)    O(n^2)    O(1)               对有序性敏感    稳定
选择    O(n^2)    O(n^2)    O(n^2)    O(1)               交换次数少    不稳定
直插    O(n^2)    O(n^2)    O(n)    O(1)               适合已经有序    稳定
希尔    O(nlogn)    O(nlogn)    O(nlogn)    O(1)               引入增量以提速 不稳定
快排    O(nlogn)    O(nlogn)    O(n^2)    O(logn)               综合性能最强    不稳定
归并    O(nlogn)    O(nlogn)    O(nlogn)    O(N)               空间换时间    稳定
堆    O(nlogn)    O(nlogn)    O(nlogn)    O(1)               利用堆结构    不稳定    
计数    O(n+k)    O(n+k)    O(n+k)    O(k)                空间换时间    稳定
桶    O(n+k)    O(n+k)    O(n^2)    O(n+k)                空间换时间    稳定
基数    O(n*K)    O(n*K)    O(n*K)    O(N+K)                空间换时间    稳定    
    

猜你喜欢

转载自blog.csdn.net/weixin_48994377/article/details/108164051