首页 > 其他分享 >数据结构4

数据结构4

时间:2023-08-14 22:22:53浏览次数:37  
标签:排序 复杂度 算法 查找 哈希 数据结构 数据

算法:
数据结构中的算法,指的是数据结构所具备的功能
解决特定问题的方法。学习的前辈们的一些优秀的经验总结
算法的五大特征:
(1)有穷性。一个算法必须总是在执行有穷步后结束,且每一步都必须在有穷时间内完成。
(2) 确定性。对千每种情况下所应执行的操作,在算法中都有确切的规定,不会产生二义性, 使算法的执行者或阅读者都能明确其含义及如何执行。
(3) 可行性。算法中的所有操作都可以通过已经实现的基本操作运算执行有限次来实现。
(4) 输入。一个算法有零个或多个输入。当用函数描述算法时,输入往往是通过形参表示的, 在它们被调用时,从主调函数获得输入值。
(5) 输出。一个算法有一个或多个输出,它们是算法进行信息加工后得到的结果,无输出的 算法没有任何意义。当用函数描述算法时,输出多用返回值或引用类型的形参表示。

如何评价一个算法:
时间复杂度:
由于计算机的性能不同,无法准确地确定一个算法的执行时间,因此使用执行算法的次数来代表算法的时间复杂度,一般用O(公式)来表示
注意:算法的时间复杂度不能完全反映一个算法的实际时间,有些算法看似时间复杂度高,但是速度也快,例如选择排序
常见的时间复杂度:
//O(1)
printf("%d\n",num);

//O(logN)
for(int i=1;i<=N;i*=2)
{
    printf("%d\n",i);
}

//O(N)
for(int i=0;i<N;i++)
{
    printf("%d\n",i);
}

//O(NlogN)
for(int i=0;i<N;i++)
{
    for(int j=0;j<N;j/=2)
    {
        printf("%d\n",i);
    }
}

//  O(N^2)
for(int i=0;i<N;i++)
{
    for(int j=0;j<N;j++)
    {
        printf("%d\n",i);
    }
}

空间复杂度:
执行一个程序(算法)所需要的内存空间的大小,是对一个算法在运行过程中临时占用存储空间大小的衡量
通常来说,只要这个算法不涉及动态分配内存以及递归,通常空间复杂度为O(1)

例如:求第N项斐波那契数列,空间复杂度为O(N),因为用到了递归

注意:一个算法的时间复杂度和空间复杂度,往往是相互影响的,如何选择根据实际情况

分治:
是一种算法思想,而不是某种特定的算法,分治就是把一个大而复杂的问题,分解成很多小而简单的问题,利用计算机强大的计算能力来解决所有小问题,从而解决最开始的问题

实现分治的具体方法:循环、递归

查找算法:
顺序查找:
对待查找的数据没有特殊要求,从头到尾逐一查找比较,在小规模数据的查找中较为常见。平均效率较低
时间复杂度是O(N)

二分查找(折半查找)
    对待查找的数据必须有序,从中间位置开始查找,如果中间值比key要大,则从左边继续二分查找,否则从右边二分查找
    时间复杂度O(logN)

块查找(权重查找):
    是一种数据处理的思想,不是特定的算法实现,当待处理的数据量很巨大时,可以根据数据的特征进行分块处理,然后再对每块数据进行查找。
    例如:英文词典、通讯录

哈希查找Hash:
    先把待查找的数据经过哈希函数,计算出该数据在哈希表中的位置,然后做标记,后续就可以很方便地查找数据,它的时间复杂度最高能到O(1)
    缺点:该算法有很大的局限性,不适合查找浮点型数据,需要额外的内存空间、空间复杂度高,是一种典型的以空间换时间的算法。
    哈希函数设计方法:
        1、直接定址法:直接把数据作为它在哈希表中的位置来做标记
        2、数据分析法:先分析出数据的最大值、最小值,然后通过 最大值-最小值+1 来确定哈希表的长度,根据哈希函数 数据-最小值 进行标记和查找哈希表
        3、平方取中法、折叠法、随机数法等
    注意:无论哪种方法都可能会出现哈希冲突(有重复数据时无法确定具体数据),一般采用链表配合解决
    Hash函数的应用:MD5加密算法、SHA-1都属于Hash算法 

排序算法:
排序算法的稳定性:
在待排序的数据中,对于数值相同的数据,在整个排序过程中如果不会改变他们原来的先后顺序,则认为该排序算法是稳定的

冒泡排序:
    数据左右比较,把较大的数据交换到右边,往后重复以上操作,直到把最大的数据交换到最后,特点是该算法对数据的有序性敏感,如果在一次的排序过程中没有发生一次交换
    那么意味着数据已经有序。可以立即停止排序。
    时间复杂度:平均:O(N^2) 最优:O(N)
    适合待排序的数据基本有序时,则冒泡的效率非常高。
    稳定的

选择排序:
    假设最开始的位置是最小值并记录下标,然后与后面所有数据比较,如果有比min位置更小的数,那么更新min,结束后min的下标与开始时发生过改变,才进行交换到开始位置。
    虽然时间复杂度较高,但是数据交换次数比较少,因此实际的运行速度并不慢(数据交换比数据比较耗时间)
    时间复杂度:O(N^2)
    不稳定  例如  10 10 1


插入排序:
    把数据看成两个部分,前部分是有序的,把剩余部分的数据逐个往前比较,如果比前面的数小,前面的数往后移动一位,继续往前比较,直到遇到更小的数,那么该数字的后一个位置便是
    需要插入的位置
    适合对已经排序后的数据,新增数据后再排序
    时间复杂度:O(N^2)
    稳定的

希尔排序:
    是插入排序的增强版,由于插入排序时数据移动的步长较短,都是1,所以增加了增量的概念,通过不停地缩减增量,最终步长还是变回1,可以提高排序的效率
    当待排序数据远离最终位置时,希尔排序的效率高于插入排序
    时间复杂度:O(NlogN)~O(N^2)
    不稳定

快速排序:
    在待排序数据中先找一个标杆位置p,备份p位置的值val,记录左标杆l、右标杆r,l从p的左边找比val大的数,找到后赋值给p位置,更新p到l,然后r从p的右边找比val小的数
    找到后赋值给p的位置,更新p到r
    循环往复,直到l和r重合,把val还原回p位置完成一次快排,然后用同样的方式对p的左右进行快排

    它的综合性能最优,因此得名快速排序,笔试时考的最多
    时间复杂度:O(NlogN)
    不稳定

堆排序:
    把待排序数据当作完全二叉树看待,先把二叉树调整成大顶堆结构,把根节点的值与末尾节点的值交换,然后数量范围-1,重新从上到下调整回大顶堆,继续以上操作,
    直到数量为1时结束,此时全部数据就从小到大排序了。
    既可以顺序实现,也可以递归实现
    时间复杂度:O(N*logN)
    不稳定

归并排序:
    首先需要把数据拆分成单独的个体,然后按照从小到大的顺序比较后排序到一段临时空间中,把排序后的临时空间中的数据拷贝回原内存,然后依次把有序的个体继续以上
    操作合并成更大的有序部分
    归并排序不需要交换数据,减少了交换的耗时,但是需要额外的存储空间,是一种典型的以空间换时间的算法
    时间复杂度:O(N*logN)
    稳定的 


计数排序:
    找出待排序数据中的最大、最小值,创建长度为最大值-最小值+1的哈希表,根据哈希函数 数据-最小值 当做哈希表的下标并对所有数据做标记,然后从头遍历哈希表,
    当某个位置的值大于0,把该位置的下标+最小值的结果依次被放回原数据内存中

    是一种典型的以空间换时间的算法,理论上该算法的速度非常快的,它不是基于比较多排序算法,在一定范围内的整数排序中快于任意一种基于比较的排序算法,但是有很大的局限性
    只适合整型数据排序,数据的差值不宜太大,重复数比较多的情况下性价比很高
    时间复杂度:O(n+k)(其中的k是整数的范围)
    稳定的

桶排序:
    一般是把数据根据数值分到不同的“桶”,通过不同的,合适的其他排序算法对“桶”中的数据进行排序,然后再把各个“桶”的数据依次拷贝拷贝回原内存中
    桶排序是一种降低排序规模的排序思想,也是以空间换时间的算法。
    缺点:如何分桶、桶如何定义,都需要针对具体待排序的数据进行分析后才能确定
    桶排序的稳定性取决于桶内排序使用的算法
    有些资料上认为桶排序可以做到稳定,所以认为桶排序稳定
基数排序:
    33 23 51 123 5344 1 663 346 31 78
    51 1 31 33 23 123 663 5344 346 78
    1 23 123 31 33 5344 346 51 663 78
    1 23 31 33 51 78 123 5344 346 663
    1 23 31 33 51 78 123 346 663 5344
0   
1   
2   
3   
4   
5   
6   
7   
8   
9

标签:排序,复杂度,算法,查找,哈希,数据结构,数据
From: https://www.cnblogs.com/c-learnmore/p/17629943.html

相关文章

  • 线性表【数据结构学习-青岛大学王卓老师】
    https://www.bilibili.com/video/BV1qz4y1p767/线性表线性表的初始化(顺序表)StatusInitList(SqList&L){L.elem=(ElemType*)malloc(sizeof(ElemType)*MAXSIZE);if(!L.elem)exit(OVERFLOW);L.length=0;returnOK;}线性表的销毁voi......
  • redis数据结构字典
    redis数据结构字典数据结构Redis的字典使用哈希表作为底层实现,一个哈希表里面可以有多个哈希表节点,而每个哈希表节点就保存了字典中的一个键值对。哈希表typedefstructdictht{//哈希表数组dictEntry**table;//哈希表大小unsignedlongsize;//哈希表大小掩码,用于......
  • 数据结构(哈夫曼树):判定编码方案是否为前缀编码
    前缀编码定义:(字符集中)任一编码都不是其它字符的编码的前缀(字符集中)任一编码都不是其它字符的编码的前缀(字符集中)任一编码都不是其它字符的编码的前缀重要的话说三遍!例:(1)找出下面不是前缀编码的选项A{1,01,000,001}B{1,01,011,010}C{0,10,110,11}D{0,1,00,11}第一步:看A中的第一个数1,看看其他......
  • redis数据结构链表
    redis数据结构链表数据结构链表节点typedefstructlistNode{//前置节点structlistNode*prev;//后置节点structlistNode*next;//节点的值void*value;}listNode;多个listNode可以通过prev和next指针组成双端链表链表typedefstructlist{//表头节点......
  • redis数据结构sds
    简单字符串sds数据结构structsdshdr{//记录buf数组中已使用字节的数量//等于SDS所保存字符串的长度intlen;//记录buf数组中未使用字节的数量intfree;//字节数组,用于保存字符串charbuf[];};特性空间预分配空间预分配用于优化SDS的字符串年增长操作:当SD......
  • 考研数据结构——每日一题[哈希表]
    840.模拟散列表维护一个集合,支持如下几种操作:Ix,插入一个数x;Qx,询问数x是否在集合中出现过;现在要进行N次操作,对于每个询问操作输出对应的结果。输入格式第一行包含整数N,表示操作数量。接下来N行,每行包含一个操作指令,操作指令为Ix,Qx中的一种。输出格式对于每......
  • Redis设计与实现——数据结构(二刷)
    SDS动态字符串Redis是c语言实现的,传统c字符串存在不可变导致的频繁内存分配,一些API函数可能引起缓冲区溢出等问题。Redis在c字符串的基础上,封装实现了SDS动态字符串,能够根据每次存储关键字的大小自动申请额外缓冲区内存,避免频繁申请和缓冲区溢出问题。SDS定义str......
  • 数据结构与算法 --- 如何分析排序算法
    引言排序算法是最基础的算法,对于排序算法,除学习算法原理,代码实现之外,更重要的是学习每个算法的特点,知道在什么场景下选择那种算法。那一定是选择时间复杂度最低的排序算法就是最优的吗?可以从以下几个方面分析一下。排序算法的执行效率对于排序算法的执行效率,一般从以下几个方......
  • 数据结构与算法 --- 组数、链表、栈和队列(一)
    数组、链表、栈和队列是四种基础数据结构,他们是高级、复杂的数据结构和算法的基础。本篇先来讲述数组,链表,及算法的优化策略。数组定义数组:数组是一种线性表数据结构,它用一组连续的内存空间存储一组具有相同类型的数据。定义中有三个关键词:线性表连续的内存空间相同类型数......
  • 数据结构与算法 --- “哨兵”思想
    引言哨兵思想是指在算法中使用一个特殊值来检测或标记某些条件的发生,它的目的是为了简化代码,并使其更容易理解,常常用于在循环中优化边界条件的判断。介绍在算法中,"哨兵"思想是指在循环中设置一个特殊的元素(称为哨兵),以便在循环过程中能够更高效地处理某些边界情况或结束条件。......