zoukankan      html  css  js  c++  java
  • 数据结构相关知识整理

    用两个栈实现一个队列

    栈:后进先出

    队列:先进先出

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

    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

      堆和队列的区别

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

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

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

  • 相关阅读:
    第三方驱动备份与还原
    Greenplum 解决 gpstop -u 指令报错
    yum安装(卸载)本地rpm包的方法(卸载本地安装的greenplum 5.19.rpm)
    Java JUC(java.util.concurrent工具包)
    netty 详解(八)基于 Netty 模拟实现 RPC
    netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包
    netty 详解(六)netty 自定义编码解码器
    netty 详解(五)netty 使用 protobuf 序列化
    netty 详解(四)netty 开发 WebSocket 长连接程序
    netty 详解(三)netty 心跳检测机制案例
  • 原文地址:https://www.cnblogs.com/Annetree/p/13511484.html
Copyright © 2011-2022 走看看