数据结构与算法知识点

一、数据结构

  1. 数组

一种线性表结构,连续的内存空间存储相同数据类型的数据。

说到线性表,有必要列出一下:

名称 种类
线性表 数组、链表、队列、栈
非线性表

二叉树、堆、图

  数组最大的优势是:可以通过下标随机访问,时间复杂度为O(1)(由于线性的,且内存空间连续)。

  数组劣势是:删除和插入比较费劲,时间复杂度为O(n)(需要移动删除和插入元素后的所有元素)。

STL中的vector(动态数组)在业务可以直接拿来使用。vector的size和capacity有什么区别?

     2.链表

链表经常和数组进行比较,数组在内存分配的时候要求比较苛刻,必须需要连续一块内存空间;而链表则不需要,链表(单链表)的数据结构里定义了一个next指针,用这个指针把所有的结点都连接起来,所以链表就可以利用自身的优势把内存分散的内存片利用起来,进而没有分配大小的限制(内存空间够用的情况下)。

  链表的最大优势是:删除和插入时间复杂度为O(1);注意:这里指的是插入和删除指定位置,如果操作的位置还需要查找,查找的时间复杂度就为O(n)。

 链表的劣势是:不能像数组那样随机访问,查找时间复杂度为O(n)。

  • 单链表

单链表的定义:

struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
};
  • 双向链表

双向链表能O(1)的时间复杂度找到前驱结点,在删除和查找方面起到很重要的作用。

双向链表的定义:

struct ListNode {
     int val;
     ListNode *pre;
     ListNode *next;
     ListNode(int x) : val(x), pre(NULL), next(NULL) {}
};
  • 循环链表

循环链表是在上面两种链表上形成一个环。

链表编程练习:链表

     3.栈

栈特点是:先进后出,只能从一端(栈顶)插入(push)和弹出(pop)。

栈的应用场景:函数的调用(用栈来保存临时变量,在函数递归时表现的尤为突出)、比如浏览器的前进后退功能。

栈可用数组(顺序栈)和链表(链式栈)实现。

    4.队列

队列和栈经常放在一起作对比,队列是先进先出,从队列的尾入队(push),从队列的头出队(pop)。

队列可用数组(顺序队列)和链表(链式队列)实现。

  • 环形队列

        在线程池上的应用。

      5.散列表

     通过散列函数将值(value)映射到键值(key),通过这种value=hash(key)的对应关系,能够快速的查找到集合中的该元素。最简单的就是数组,数组就是通过下标和值建立对应关系,才使查询元素的时间复杂度为O(1)。

     散列表还有个问题,就是冲突的问题,怎么解决呢?

  • 开放寻址法:遇到冲突的时候,将元素插入到空闲的位置,查找的时候使用线性探测、二次探测、多重散列。这种方法在空闲位置少的情况下,查找时间复杂度会退化为O(n)。
  • 拉链法:遇到冲突的时候,一次将冲突元素放入对应的链表中。也可使用红黑树、跳表代替链表。

散列应用场景:快速查找,或者检测元素在不在集合里。

思考题1:有10万条访问URL的日志,怎么按访问次数给URL排序?

解法:第一步,统计  hash(URL) = count,即URL作为key,访问次数count作为value;第二步,按照value(即count)排序。

思考题2:有两个10万大小的字符串数组,怎么找出两个数组相同的字符串?

解法:第一步,给第一个数组的字符串做哈希, hash(str) = count,即str作为key,出现次数count作为value;第二步,从第二个数组拿出字符串,去建立好的哈希表里查找,如果value > 0,则说明该字符串在第一个数组已经出现过。

另外,哈希算法(散列只是哈希算法的一种应用)的应用不止这些,还有:校验(MD5、SHA1、SHA256),一致哈希(分布式集群的应用)

     6.二叉树

树的属性:

  • 节点深度:根节点-->节点的路径
  • 节点高度:节点-->叶子节点的最长路径

二叉树的类型:

  • 满二叉树:叶子节点全在最底层,并且除叶子节点外,每个节点都有两个子节点。
  • 完全二叉树:叶子节点全在最底两层,最后一层都靠左排列,其他节点的子节点数目达到最大。

二叉树的遍历:二叉树

二叉查找树:任意一个节点,左子树的值小于该节点的值,而右子树大于该节点的值。

         二叉查找树也经常拿来和散列表比较,(1)虽然散列表的插入、删除和查找都能做到O(1)级别的时间复杂度,而要得到有序的序列,就必须去排序,而二叉查找树的中序遍历可以得到有序的序列(O(n)时间复杂度就可以得到有序序列);(2)散列经常面临冲突的问题,构造哈希函数比较复杂,以至于散列不是很友好,反而二叉查找树插入、删除和查找的时间复杂度能够稳定在O(logn)级别。

  • 平衡二叉查找树(AVL)

二叉查找树最坏的情况下会退化为链表,所以要求树的任意左右子树高度差不能超过1,从定义看满二叉树、完全二叉树满足的平衡的条件,但并不是查找树,平衡二叉查找树就是在二叉查找树基础上再要求平衡。红黑树就是广泛应用的AVL。

            二叉查找树的查找和插入比较简单,删除稍有点复杂。代码实现:

     7.堆

堆的定义:(1)堆是完全二叉树;(2)堆的节点值必须都大于(或小于)其子树的值(这点和二叉查找树要区别开来)。

堆的应用:优先队列

代码实现:建堆、插入、删除、排序

     8.跳表

跳表在redis中的应用,是因为跳表能够进行区间查找。

     9.图

  • 广度优先搜索(BFS)
  • 深度优先搜索(DFS)

    10.Trie树(字典树)

字典树的应用:自动补全功能(输入法不全、写代码自动补全、搜索引擎输入字符自动补全)

二、算法

  1. 递归  递归的理解
  2. 排序  排序
  3. 二分查找  二分查找
  4. 搜索
  5. 哈希
  6. 贪心
  7. 分治
  8. 回溯
  9. 动态规划
  10. 字符串匹配

你可能感兴趣的:(算法,数据结构)