用两个栈实现一个队列

栈:后进先出

队列:先进先出

要使用两个栈实现队列(先进先出),主要思路是

1.插入一个元素:直接将元素插入stack1即可。
2.删除一个元素:当stack2不为空时 ,直接弹出栈顶元素,当stack2为空时,将stack1元素逐个弹出并压入stack2,然后再弹出栈顶元素。

用我的话说就是两个先进后出就变成先进先出了

具体可参考 https://www.cnblogs.com/clwsec/p/11586972.html

平衡二叉树

平衡树(Balance Tree,BT) 指的是,任意节点的子树的高度差都小于等于1。常见的符合平衡树的有,B树(多路平衡搜索树)、AVL树(二叉平衡搜索树)等。

它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

具体可参考 https://www.cnblogs.com/zhangbaochong/p/5164994.html

双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

实现链表翻转有以下两种方法:

  • 建立新链表,依次从旧链表中复制节点,并将其作为头。空间复杂度为O(N)
  • 原地翻转 。空间复杂度为O(1)

typedef int eleType;
typedef struct Node{
    eleType ele;
    struct Node* next;
}Node, *pNode;

pNode node = (pNode)malloc(sizeof(pNode));
        node->ele = i;
        node->next = NULL;
        temp->next = node;

详见 https://blog.csdn.net/kid1ing/article/details/67638061

二叉树遍历方法

给定 先序+中序 or 后序+中序 可以唯一确定一颗二叉树

  1. 而 先序+后序 不能
  2.  
      A
  3.  
    /
  4.  
    B
  5.  
    前序遍历: AB, 后序遍历: BA
  6.  
    A
  7.  
    \
  8.  
      B
  9.  
    前序遍历: AB, 后序遍历: BA
     
    海量数据处理 - 10亿个数中找出最大的10000个数(top K问题)

    方法一、先拿10000个数建堆,然后一次添加剩余元素,如果大于堆顶的数(10000中最小的),将这个数替换堆顶,并调整结构使之仍然是一个最小堆,这样,遍历完后,堆中的10000个数就是所需的最大的10000个。建堆时间复杂度是O(mlogm),算法的时间复杂度为O(nmlogm)(n为10亿,m为10000)。

     

        方法二(优化的方法):可以把所有10亿个数据分组存放,比如分别放在1000个文件中。这样处理就可以分别在每个文件的10^6个数据中找出最大的10000个数,合并到一起在再找出

    最终的结果。

    哈夫曼树

    哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+ Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。
            构造哈夫曼树的算法如下:
            1)对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,..., Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。
            2)在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
            3)从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
            4)重复2)和3),直到集合F中只有一棵二叉树为止。

    哈夫曼树应用-哈夫曼编码

    哈夫曼树的一个经典应用就是哈夫曼编码。在数据通信中,经常需要将传送的文字转换成二进制字符串,这个过程就是编码。哈夫曼编码是一种变长的编码方案,其核心就是使频率越高的码元(这个词不知用的是否准确,就是要编码的对象,可以是字符串等等了)采用越短的编码。编码过程就根据不同码元的频率(相当于权值)构造出哈夫曼树,然后求叶子节点到根节点的路径,其中节点的左孩子路径标识为0,右孩子路径标识为1。对于上面的例子,权值为1的节点编码为000,权值为3的节点编码为001,权值为5的节点编码为01,权值为7的节点编码为1。

    详见 https://www.cnblogs.com/aaron911/p/11058017.html

     

    单链表特点

    当访问过一个节点后,只能接着访问他的后继节点,而无法访问前驱节点。

    优先队列

    普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。

    在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。

    首先要包含头文件#include<queue>, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队。

    优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。

    定义:priority_queue<Type, Container, Functional>
    Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。

    当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。

    //升序队列,小顶堆
    priority_queue <int,vector<int>,greater<int> > q;
    //降序队列,大顶堆
    priority_queue <int,vector<int>,less<int> >q;
    
    //greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

    详见 https://www.cnblogs.com/huashanqingzhu/p/11040390.html

    堆和队列的区别

    队列是先进先出,于堆而言却没有这个特性,两者都是存放临时数据的地方

    栈也称为堆栈,是一种线性表。

    堆栈的特性: 最先放入堆栈中的内容最后被拿出来,最后放入堆栈中的内容最先被拿出来, 被称为先进后出、后进先出。