算法与数据结构

 

常见算法类型

排序算法

十大经典排序算法(动图演示)

image

  • 冒泡排序
  • 快速排序
      void QSort(vector<int> &arr, int left, int right) {
      	if (left >= right) return;
    
      	int low = left;
      	int high = right;
    
      	int key = arr[left];
      	while (left < right) {
      		while (left < right && arr[right] >= key) right--;
      		arr[left] = arr[right];
      		while (left < right && arr[left] <= key) left++;
      		arr[right] = arr[left];
      	}
      	arr[left] = key;
      	QSort(arr, low, left - 1);
      	QSort(arr, left + 1, high);
      }
    
  • 堆排序
  • 二叉堆本质上是一种完全二叉树,分为最大堆和最小堆。
    • 大顶堆:priority_queue<int>,即 priority_queue<int, vector<int>, less<int>> q;
    • 小顶堆:priority_queue<int, vector<int>, greater<int>> q;
  • 二叉树前序、中序、后序递归遍历及非递归遍历。
    • 前序遍历:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
    • 中序遍历:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
    • 后序遍历:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
class Solution {
public:
    // 前序,根左右
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        if (root == nullptr) return ans;

        stack<TreeNode*> s;
        s.push(root);
        while (!s.empty()) {
            TreeNode* node = s.top();
            s.pop();
            ans.push_back(node->val);
            if (node->right) s.push(node->right);
            if (node->left) s.push(node->left);
        }

        return ans;
    }

    // 中序,左根右
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        if (root == nullptr) return ans;

        stack<TreeNode*> s;
        TreeNode* node = root;
        while (node || !s.empty()) {
            while (node) {
                s.push(node);
                node = node->left;
            }
            node = s.top();
            s.pop();
            ans.push_back(node->val);
            node = node->right;
        }
        return ans;
    }

    // 后续,根右左的逆序
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;
        if (root == nullptr) return ans;

        stack<TreeNode*> s;
        s.push(root);
        while (!s.empty()) {
            TreeNode* node = s.top();
            s.pop();
            ans.push_back(node->val);
            if (node->left) s.push(node->left);
            if (node->right) s.push(node->right);
        }
        reverse(ans.begin(), ans.end());

        return ans;
    }
};

常用数据结构

务必熟悉底层原理和实现

  • 链表、栈、队列、树(二叉树、平衡二叉树、红黑树、B树、B+树、哈夫曼树、字典树)、跳表、图

AVL树、红黑树

  • 红黑树:漫画:什么是红黑树?(整合版)
  • B-树:漫画:什么是B-树?
  • B+树:漫画:什么是B+树?
  • AVL树(平衡二叉树)(AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis)本质上还是一棵二叉搜索树,它的特点是:
    • 1.本身首先是一棵二叉搜索树。
    • 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。
  • 红黑树是一颗AVL树,同时满足下面的特性:
    • 1.结点是红色或黑色。
    • 2.根结点是黑色。
    • 3.每个叶子结点都是黑色的空结点(NIL结点)。
    • 4 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)
    • 5.从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。
  • 在需要频繁查找时,选用AVL树更合适,在需要频繁插入删除时,选用红黑树更合适。
  • 一个m阶的B-树具有如下几个特征:
    • 1.根结点至少有两个子女。
    • 2.每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
    • 3.每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
    • 4.所有的叶子结点都位于同一层。
    • 5.每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划。
  • B-树主要用于文件系统以及部分数据库索引,比如著名的非关系型数据库MongoDB。大部分关系型数据库比如MySql则使用B+树作为索引。 image
  • 一个m阶的B+树具有如下几个特征:
    • 1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
    • 2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
    • 3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。 image
  • B+树的优势:
    • 1.单一节点存储更多的元素,使得查询的IO次数更少。
    • 2.所有查询都要查找到叶子节点,查询性能稳定。
    • 3.所有叶子节点形成有序链表,便于范围查询。

Hash表设计、一致性Hash

一致性Hash:漫画:什么是一致性哈希?

Hash表设计:
  • 哈希函数的设计:对于构造哈希来说,主要包括直接地址法、平方取中法、除留余数法等
  • 解决哈希冲突
    • 开放定址法: 开放地址法有个非常关键的特征,就是所有输入的元素全部存放在哈希表里,也就是说,位桶的实现是不需要任何的链表来实现的,换句话说,也就是这个哈希表的装载因子不会超过1。它的实现是在插入一个元素的时候,先通过哈希函数进行判断,若是发生哈希冲突,就以当前地址为基准,根据再寻址的方法(探查序列),去寻找下一个地址,若发生冲突再去寻找,直至找到一个为空的地址为止。所以这种方法又称为再散列法。
    • 再哈希法:当发生哈希冲突时使用另一个哈希函数计算地址值,直到冲突不再发生。这种方法不易产生聚集,但是增加计算时间,同时需要准备许多哈希函数。
    • 链地址法:将所有哈希值相同的Key通过链表存储。key按顺序插入到链表中
    • 建立公共溢出区:建立一个公共溢出区域,把hash冲突的元素都放在该溢出区里。查找时,如果发现hash表中对应桶里存在其他元素,还需要在公共溢出区里再次进行查找。

推荐书籍

  • 《大话数据结构》适合入门学习

  • 《剑指offer》必刷66题

  • 《算法导论》尽量看,能啃完就是大神