精华内容
下载资源
问答
  • 本来是自己为了自动签到的,把包给抓了,大家有需求的可以参考参考 小小签到获取签到列表 请求方式get http://api-xcx.qunsou.co/xcx/qq/checkin/v3/list?type=5&page=1&count=10&access_token=...

    本来是自己为了弄自动签到的,把自己抓到的数据分享给大家,大家有需求的可以参考参考

    小小签到获取签到列表
    请求方式get
    http://api-xcx.qunsou.co/xcx/qq/checkin/v3/list?type=5&page=1&count=10&access_token=[token值]&tag=0
    =======返回到的数据==========
    {
      "sta": 0,
      "msg": "",
      "data": [
        {
          "cid": "",
          "title": "",//签到标题
          "banner": "",//图标
          "start_date": 1581868800,
          "end_date": 4670495999,
          "start_time": 0,
          "end_time": 86399,
          "time_list": [
            [
              39600,
              46800
            ]
          ],
          "owner": "",//发起人
          "owner_pic": "",//发起人头像
          "no_forward": 0,
          "gold_name": 0,
          "name_color": "",
          "adv_avatar": "",
          "is_owner": 0,
          "pic_text": 1,
          "join_num": "43",//人数
          "status": 1,
          "censor_status": 0,
          "fee": 0,
          "top": 1,
          "has_check": 1,
          "template": 0,
          "show_remove_tip": 0
        }
      ],
      "show_summary": 0,
      "show_remove_tip": 0
    }
    ========================
           发送签到内容
    ===========请求头========
    POST /xcx/qq/checkin/v3/doit HTTP/1.1
    User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; DUK-AL20 Build/MXC89K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.119 Mobile Safari/537.36 QQ/MiniApp QQ/8.3.5
    Referer: https://appservice.qq.com/1108310646/1.1.1/page-frame.html
    content-type: application/json
    Content-Length: 301
    Host: api-xcx.qunsou.co
    Connection: Keep-Alive
    Accept-Encoding: gzip
    ========================
    =====post数据内容======
    {
      "cid": "",//[必填]
      "formid": "",//有没有都无所谓
      "text": "",//签到文本内容[必填]
      "pic": [],
      "audio": [],
      "audio_len": [],
      "video": [],
      "access_token": "",//[必填]
      "steps": -1,
      "mp_url": "",
      "mp_title": "",
      "mp_icon": ""
    }
    ====================

     

    展开全文
  • qq好友列表获取之动态爬虫清洗爬取qq好友列表数据 - 获取qq好友ip、群、群成员列表。我们的好友列表要从 qzone 获取,现在打开 qzone 的链接https://h5.qzone.qq.com/mqzone/index并且登陆。 具体步骤: 1、分析...

    qq好友列表获取之动态爬虫清洗爬取qq好友列表数据 - 获取qq好友ip、群、群成员列表。我们的好友列表要从 qzone 获取,现在打开 qzone 的链接 https://h5.qzone.qq.com/mqzone/index 并且登陆。

    具体步骤:

    1、分析qzone请求
    2、分析参数来源
    3、仿照数据请求

    上次写的一个qzone登陆写的不详细这次决定写一个详细分析qzone js 获取好友列表

    分析qzone请求

    我们的好友列表要从 qzone 获取,现在打开 qzone 的链接 https://h5.qzone.qq.com/mqzone/index 并且登陆。

    你可能会说你在逗我,这特么哪里来的qq好友列表
    别急,好友列表肯定是有的不然你发表说说怎么@你的好友呢

    说到@好友都明白了吧,我们的好友列表接口就从这里开始拦截接口请求。
    先把打开我们发说说的那个框框,再把浏览器开启调试模式,清空网络请求拦截列表

    qq好友列表获取
    qq好友列表获取

    现在你应该在发说说的那个界面,点一下说说框下面的 @符号

    qq好友列表获取
    qq好友列表获取

    盯住网络请求那一块,找一下那个像是获取好友列表的,发现一共就6个请求,我一眼就看到了mfriend_list 接口意思很直白啊

    qq好友列表获取
    qq好友列表获取

    qq好友列表已经找到,接下来就是分析参数了,这个过程很痛苦

     

    分析参数来源

    首先点我刚刚说到的那一条请求记录 就是这样子的 我对自己的qq号打了码毕竟这个东西获取到可以直接用cookie登陆的

    qq好友列表获取
    qq好友列表获取

     

    这里可能有人会说,为什么不直接点击拦截列表上面有个可以定位js发出请求的位置,这样找分析请求参数不是更简单吗
    这边呢我只能说我之前也找过,但是找不到获取同行qq好友的软件,因为点击过去找到的是封装类的位置。

    这边参数呢不多 六个 需要分析的就两个
    qzonetoken c2176b5d6f0deff03d0dd0f59f26e51c2b408aa83419d416c737cc1b21d1e913c861ca780ad34ff4293ca5640b69
    g_tk:1760587213
    res_uin:***
    res_type:normal
    format:json
    timestamp 时间戳

    我们现在看一下这个 qzonetoken 使用全局搜索找一下看是不是写在静态页面中的

    qq好友列表获取
    qq好友列表获取

    继续搜索 window.shine0callback

    发现都是一个结果。。。。 后面我试着搜索一下html 里面 发现竟然真的有
    qq好友列表获取

    发现都是一个结果。。。。 后面我试着搜索一下html 里面 发现竟然真的有

    qq好友列表获取
    qq好友列表获取

    window.shine0callback = 自执行函数
    所以呢 qzonetoken 参数直接用 window.shine0callback 就好了

    继续全局搜索 g_tk

    qq好友列表获取

    这边呢有三个方法获取token
    1、userHelper.getPskeyToken()
    2、userHelper.getToken()
    3、user.getToken()

    我们先在控制台执行一下这些方法

    qq好友列表获取
    qq好友列表获取

    发现 user 能执行也和请求的参数对上了,不过我还是想找一下 userHelper 这个东西

    先把ajax.js 这个类给弄到本地来 搜索 userHelper

    qq好友列表获取
    qq好友列表获取

    既然写在里面的那copy到控制台就可以执行了。这个不同微信好友列表获取的方式。
    开始我把 userHelper copy进去发现少了一个getCookie,再把getCookie 也复制到控制台就好了

    qq好友列表获取

    这样子执行就能获取到 token 了

    res_uin qq号码,我在搜索静态html的时候无意间发现了可以从 FrontPage 对象中获取,当然也可以从 user 对象中获取
    res_type 固定normal
    format 固定json
    timestamp 时间戳拿一下系统时间戳就好。

    现在参数都分析完毕,qzone 的接口分析还是蛮简单的,不像某宝网站的程序

    仿照数据请求

    找到 paresHtml 函数 在这里先切换到默认窗口

    def paresHtml(self):
        self.driver.switch_to.default_content()

    获取 qzonetoken 这边直接执行window.shine0callback 就能获取

    qzonetoken = self.driver.execute_script('return window.shine0callback')

    获取 g_tk 上面说到user里面可以直接获取,那我们就偷个懒使用 user.getToken()

    g_tk = self.driver.execute_script('return user.getToken()')

    获取 res_uin 直接从user 里面 getUin()

    res_uin = self.driver.execute_script('return user.getUin()')

    获取时间戳 由于python 中的time.time()是秒,需要乘个1000

    import time
    timestamp = time.time() * 1000

    拼接url

    list = 'https://mobile.qzone.qq.com/friend/mfriend_list?' \
                   'qzonetoken=%s&g_tk=%s&res_uin=%s&res_type=normal&format=json&timestamp=%d' % ( qzonetoken, g_tk, res_uin, timestamp)

    本身我想偷懒的直接用 self.driver.get() 直接执行的 后来想想还是算了,没有一点技术含量的东西怎么好意思写呢
    最后决定使用js中的XMLHttpRequest 来模仿请求

     

      self.driver.execute_script('window.xhr = new XMLHttpRequest;')
        self.driver.execute_script('window.xhr.withCredentials=true;')
        self.driver.execute_script(
            'window.xhr.open(\'GET\',\'%s\',false)' % list)
        self.driver.execute_script('window.xhr.onload = function (e){window.xhrsuccess = window.xhr.responseText}')
        self.driver.execute_script('window.xhr.send()')
        print(self.driver.execute_script('return window.xhrsuccess'))

    请求完成后的结果是这个样子的

    qq好友列表
    qq好友列表

    下面是请求返回的结果

    {
        "code":0,
        "subcode":0,
        "message":"",
        "default":0,
        "data":{
            "gpnames":[//分组列表
                {
                    "gpid":0,//分组id
                    "gpname":"agp"//分组名称
                }
            ],
            "list":[//好友列表
                {
                  "groupid":0,//分组id
                  "isvip":1,//是否是vip 1 是 vip
                  "nick":"消费主张", //昵称
                  "remark":"消费主张",//备注
                  "searchField":"12315 消费主张 消费主张 xiaofeizhuzhang xfzz xiaofeizhuzhang xfzz",//关键字
                  "uin":12315,//qq号码
                  "viplevel":1 //qq等级
                }
            ],
            "mayknow":{
                 "allnum":0,
                  "list":null,
                  "page":1
            },
            "speciallist":null
         }
    }

    最后发一下模仿请求的源码 结合我上一篇文章的源码可以直接执行出结果,也可以获取qq好友ip

    import time
    
    def paresHtml(self):
        # 切换到默认窗口
        self.driver.switch_to.default_content()
        # 请求状态
        shine0callback = self.driver.execute_script('return window.shine0callback')
        # 一定要暂停一下不然 执行user的时候拿不到,因为懒加载
        time.sleep(1)
    
        g_tk = self.driver.execute_script('return window.user.getToken()')
        uin = self.driver.execute_script('return window.user.getUin()')
        timestamp = time.time() * 1000
    
        list = 'https://mobile.qzone.qq.com/friend/mfriend_list?' \
                'qzonetoken=%s&g_tk=%s&res_uin=%s&res_type=normal&format=json&timestamp=%d' % (
                    shine0callback, g_tk, uin, timestamp)
    
        # self.load_cookies()
        # self.driver.get(list)
    
        self.driver.execute_script('window.xhr = new XMLHttpRequest;')
    
        self.driver.execute_script(
                'window.xhr.open(\'GET\',\'%s\',false)' % list)
        self.driver.execute_script('window.xhr.onload = function (e){window.xhrsuccess = window.xhr.responseText}')
        self.driver.execute_script('window.xhr.send()')
        print(self.driver.execute_script('return window.xhrsuccess'))

    总结:

    1、qzone 里面的接口参数都差不多,总归来讲都能搜索出来
    2、qzone 压缩了js提高了分析的难度
    3、好友列表模拟请求时记得把cookie带过去否则t不认
    4、有时候登陆会登不上,拿到的好友列表数据是请先登录,删掉cookie重试即便就好

     

    更多:qq好友列表获取

    展开全文
  • 图解!24张图彻底懂九大常见数据结构!

    万次阅读 多人点赞 2020-05-24 22:23:36
    数据结构想必大家都不会陌生,对于一个成熟的程序员而言,熟悉和掌握数据结构和算法也是基本功之一。数据结构本身其实不过是数据按照特点关系进行存储或者组织的集合,特殊的结构在不同的应用场景中往往会带来不...

    ​数据结构想必大家都不会陌生,对于一个成熟的程序员而言,熟悉和掌握数据结构和算法也是基本功之一。数据结构本身其实不过是数据按照特点关系进行存储或者组织的集合,特殊的结构在不同的应用场景中往往会带来不一样的处理效率。

    常用的数据结构可根据数据访问的特点分为线性结构和非线性结构。线性结构包括常见的链表、栈、队列等,非线性结构包括树、图等。数据结构种类繁多,本文将通过图解的方式对常用的数据结构进行理论上的介绍和讲解,以方便大家掌握常用数据结构的基本知识。

    本文提纲:

     1  数组

    数组可以说是最基本最常见的数据结构。数组一般用来存储相同类型的数据,可通过数组名和下标进行数据的访问和更新。数组中元素的存储是按照先后顺序进行的,同时在内存中也是按照这个顺序进行连续存放。数组相邻元素之间的内存地址的间隔一般就是数组数据类型的大小。

     2  链表

    链表相较于数组,除了数据域,还增加了指针域用于构建链式的存储数据。链表中每一个节点都包含此节点的数据和指向下一节点地址的指针。由于是通过指针进行下一个数据元素的查找和访问,使得链表的自由度更高。

    这表现在对节点进行增加和删除时,只需要对上一节点的指针地址进行修改,而无需变动其它的节点。不过事物皆有两极,指针带来高自由度的同时,自然会牺牲数据查找的效率和多余空间的使用。

    一般常见的是有头有尾的单链表,对指针域进行反向链接,还可以形成双向链表或者循环链表。

    链表和数组对比

    链表和数组在实际的使用过程中需要根据自身的优劣势进行选择。链表和数组的异同点也是面试中高频的考察点之一。这里对单链表和数组的区别进行了对比和总结。

     3  跳表

    从上面的对比中可以看出,链表虽然通过增加指针域提升了自由度,但是却导致数据的查询效率恶化。特别是当链表长度很长的时候,对数据的查询还得从头依次查询,这样的效率会更低。跳表的产生就是为了解决链表过长的问题,通过增加链表的多级索引来加快原始链表的查询效率。这样的方式可以让查询的时间复杂度从O(n)提升至O(logn)。

    跳表通过增加的多级索引能够实现高效的动态插入和删除,其效率和红黑树和平衡二叉树不相上下。目前redis和levelDB都有用到跳表。

    从上图可以看出,索引级的指针域除了指向下一个索引位置的指针,还有一个down指针指向低一级的链表位置,这样才能实现跳跃查询的目的。

     

     4  栈

    栈是一种比较简单的数据结构,常用一句话描述其特性,后进先出。栈本身是一个线性表,但是在这个表中只有一个口子允许数据的进出。这种模式可以参考腔肠动物...即进食和排泄都用一个口...

    栈的常用操作包括入栈push和出栈pop,对应于数据的压入和压出。还有访问栈顶数据、判断栈是否为空和判断栈的大小等。由于栈后进先出的特性,常可以作为数据操作的临时容器,对数据的顺序进行调控,与其它数据结构相结合可获得许多灵活的处理。

     

     5  队列

    队列是栈的兄弟结构,与栈的后进先出相对应,队列是一种先进先出的数据结构。顾名思义,队列的数据存储是如同排队一般,先存入的数据先被压出。常与栈一同配合,可发挥最大的实力。

     6  树

    树作为一种树状的数据结构,其数据节点之间的关系也如大树一样,将有限个节点根据不同层次关系进行排列,从而形成数据与数据之间的父子关系。常见的数的表示形式更接近“倒挂的树”,因为它将根朝上,叶朝下。

    树的数据存储在结点中,每个结点有零个或者多个子结点。没有父结点的结点在最顶端,成为根节点;没有非根结点有且只有一个父节点;每个非根节点又可以分为多个不相交的子树。

    这意味着树是具备层次关系的,父子关系清晰,家庭血缘关系明朗;这也是树与图之间最主要的区别。

    别看树好像很高级,其实可看作是链表的高配版。树的实现就是对链表的指针域进行了扩充,增加了多个地址指向子结点。同时将“链表”竖起来,从而凸显了结点之间的层次关系,更便于分析和理解。

    树可以衍生出许多的结构,若将指针域设置为双指针,那么即可形成最常见的二叉树,即每个结点最多有两个子树的树结构。二叉树根据结点的排列和数量还可进一度划分为完全二叉树、满二叉树、平衡二叉树、红黑树等。

    完全二叉树:除了最后一层结点,其它层的结点数都达到了最大值;同时最后一层的结点都是按照从左到右依次排布。

    满二叉树:除了最后一层,其它层的结点都有两个子结点。

    平衡二叉树

    平衡二叉树又被称为AVL树,它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

    二叉排序树:是一棵空树,或者:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树。

    树的高度:结点层次的最大值

    平衡因子:左子树高度 - 右子树高度

    二叉排序树意味着二叉树中的数据是排好序的,顺序为左结点<根节点<右结点,这表明二叉排序树的中序遍历结果是有序的。(还不懂二叉树四种遍历方式[前序遍历、中序遍历、后序遍历、层序遍历]的同学赶紧补习!)

    平衡二叉树的产生是为了解决二叉排序树在插入时发生线性排列的现象。由于二叉排序树本身为有序,当插入一个有序程度十分高的序列时,生成的二叉排序树会持续在某个方向的字数上插入数据,导致最终的二叉排序树会退化为链表,从而使得二叉树的查询和插入效率恶化。

     

    平衡二叉树的出现能够解决上述问题,但是在构造平衡二叉树时,却需要采用不同的调整方式,使得二叉树在插入数据后保持平衡。主要的四种调整方式有LL(左旋)、RR(右旋)、LR(先左旋再右旋)、RL(先右旋再左旋)。这里先给大家介绍下简单的单旋转操作,左旋和右旋。LR和RL本质上只是LL和RR的组合。

    在插入一个结点后应该沿搜索路径将路径上的结点平衡因子进行修改,当平衡因子大于1时,就需要进行平衡化处理。从发生不平衡的结点起,沿刚才回溯的路径取直接下两层的结点,如果这三个结点在一条直线上,则采用单旋转进行平衡化,如果这三个结点位于一条折线上,则采用双旋转进行平衡化。

    左旋:S为当前需要左旋的结点,E为当前结点的父节点。

    左旋的操作可以用一句话简单表示:将当前结点S的左孩子旋转为当前结点父结点E的右孩子,同时将父结点E旋转为当前结点S的左孩子。可用动画表示:

    右旋:S为当前需要左旋的结点,E为当前结点的父节点。右单旋是左单旋的镜像旋转。

    左旋的操作同样可以用一句话简单表示:将当前结点S的左孩子E的右孩子旋转为当前结点S的左孩子,同时将当前结点S旋转为左孩子E的右孩子。可用动画表示:

    红黑树

    平衡二叉树(AVL)为了追求高度平衡,需要通过平衡处理使得左右子树的高度差必须小于等于1。高度平衡带来的好处是能够提供更高的搜索效率,其最坏的查找时间复杂度都是O(logN)。但是由于需要维持这份高度平衡,所付出的代价就是当对树种结点进行插入和删除时,需要经过多次旋转实现复衡。这导致AVL的插入和删除效率并不高。

    为了解决这样的问题,能不能找一种结构能够兼顾搜索和插入删除的效率呢?这时候红黑树便申请出战了。

    红黑树具有五个特性:

    1. 每个结点要么是红的要么是黑的。

    2. 根结点是黑的。

    3. 每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。

    4. 如果一个结点是红的,那么它的两个儿子都是黑的。

    5. 对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。

    红黑树通过将结点进行红黑着色,使得原本高度平衡的树结构被稍微打乱,平衡程度降低。红黑树不追求完全平衡,只要求达到部分平衡。这是一种折中的方案,大大提高了结点删除和插入的效率。C++中的STL就常用到红黑树作为底层的数据结构。

    红黑树VS平衡二叉树

    除了上面所提及的树结构,还有许多广泛应用在数据库、磁盘存储等场景下的树结构。比如B树、B+树等。这里就先不介绍了诶,下次在讲述相关存储原理的时候将会着重介绍。(其实是因为懒)

     7  堆

    了解完二叉树,再来理解堆就不是什么难事了。堆通常是一个可以被看做一棵树的数组对象。堆的具体实现一般不通过指针域,而是通过构建一个一维数组与二叉树的父子结点进行对应,因此堆总是一颗完全二叉树。

    对于任意一个父节点的序号n来说(这里n从0算),它的子节点的序号一定是2n+1,2n+2,因此可以直接用数组来表示一个堆。

    不仅如此,堆还有一个性质:堆中某个节点的值总是不大于或不小于其父节点的值。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

    堆常用来实现优先队列,在面试中经常考的问题都是与排序有关,比如堆排序、topK问题等。由于堆的根节点是序列中最大或者最小值,因而可以在建堆以及重建堆的过程中,筛选出数据序列中的极值,从而达到排序或者挑选topK值的目的。

     

     8  散列表

    散列表也叫哈希表,是一种通过键值对直接访问数据的机构。在初中,我们就学过一种能够将一个x值通过一个函数获得对应的一个y值的操作,叫做映射。散列表的实现原理正是映射的原理,通过设定的一个关键字和一个映射函数,就可以直接获得访问数据的地址,实现O(1)的数据访问效率。在映射的过程中,事先设定的函数就是一个映射表,也可以称作散列函数或者哈希函数。

    散列表的实现最关键的就是散列函数的定义和选择。一般常用的有以下几种散列函数:

    直接寻址法:取关键字或关键字的某个线性函数值为散列地址。

    数字分析法:通过对数据的分析,发现数据中冲突较少的部分,并构造散列地址。例如同学们的学号,通常同一届学生的学号,其中前面的部分差别不太大,所以用后面的部分来构造散列地址。

    平方取中:当无法确定关键字里哪几位的分布相对比较均匀时,可以先求出关键字的平方值,然后按需要取平方值的中间几位作为散列地址。这是因为:计算平方之后的中间几位和关键字中的每一位都相关,所以不同的关键字会以较高的概率产生不同的散列地址。

    取随机数法:使用一个随机函数,取关键字的随机值作为散列地址,这种方式通常用于关键字长度不同的场合。

    除留取余法:取关键字被某个不大于散列表的表长 n 的数 m 除后所得的余数 p 为散列地址。这种方式也可以在用过其他方法后再使用。该函数对 m 的选择很重要,一般取素数或者直接用 n。

    确定好散列函数之后,通过某个key值的确会得到一个唯一的value地址。但是却会出现一些特殊情况。即通过不同的key值可能会访问到同一个地址,这个现象称之为冲突。

    冲突在发生之后,当在对不同的key值进行操作时会使得造成相同地址的数据发生覆盖或者丢失,是非常危险的。所以在设计散列表往往还需要采用冲突解决的办法。

    常用的冲突处理方式有很多,常用的包括以下几种:

    开放地址法(也叫开放寻址法):实际上就是当需要存储值时,对Key哈希之后,发现这个地址已经有值了,这时该怎么办?不能放在这个地址,不然之前的映射会被覆盖。这时对计算出来的地址进行一个探测再哈希,比如往后移动一个地址,如果没人占用,就用这个地址。如果超过最大长度,则可以对总长度取余。这里移动的地址是产生冲突时的增列序量。

    再哈希法:在产生冲突之后,使用关键字的其他部分继续计算地址,如果还是有冲突,则继续使用其他部分再计算地址。这种方式的缺点是时间增加了。

    链地址法:链地址法其实就是对Key通过哈希之后落在同一个地址上的值,做一个链表。其实在很多高级语言的实现当中,也是使用这种方式处理冲突的。

    公共溢出区:这种方式是建立一个公共溢出区,当地址存在冲突时,把新的地址放在公共溢出区里。

    目前比较常用的冲突解决方法是链地址法,一般可以通过数组和链表的结合达到冲突数据缓存的目的。

    左侧数组的每个成员包括一个指针,指向一个链表的头。每发生一个冲突的数据,就将该数据作为链表的节点链接到链表尾部。这样一来,就可以保证冲突的数据能够区分并顺利访问。

    考虑到链表过长造成的问题,还可以使用红黑树替换链表进行冲突数据的处理操作,来提高散列表的查询稳定性。

     

     9  图

    图相较于上文的几个结构可能接触的不多,但是在实际的应用场景中却经常出现。比方说交通中的线路图,常见的思维导图都可以看作是图的具体表现形式。

    图结构一般包括顶点和边,顶点通常用圆圈来表示,边就是这些圆圈之间的连线。边还可以根据顶点之间的关系设置不同的权重,默认权重相同皆为1。此外根据边的方向性,还可将图分为有向图和无向图。

    图结构用抽象的图线来表示十分简单,顶点和边之间的关系非常清晰明了。但是在具体的代码实现中,为了将各个顶点和边的关系存储下来,却不是一件易事。

    邻接矩阵

    目前常用的图存储方式为邻接矩阵,通过所有顶点的二维矩阵来存储两个顶点之间是否相连,或者存储两顶点间的边权重。

    无向图的邻接矩阵是一个对称矩阵,是因为边不具有方向性,若能从此顶点能够到达彼顶点,那么彼顶点自然也能够达到此顶点。此外,由于顶点本身与本身相连没有意义,所以在邻接矩阵中对角线上皆为0。

    有向图由于边具有方向性,因此彼此顶点之间并不能相互达到,所以其邻接矩阵的对称性不再。

    用邻接矩阵可以直接从二维关系中获得任意两个顶点的关系,可直接判断是否相连。但是在对矩阵进行存储时,却需要完整的一个二维数组。若图中顶点数过多,会导致二维数组的大小剧增,从而占用大量的内存空间。

    而根据实际情况可以分析得,图中的顶点并不是任意两个顶点间都会相连,不是都需要对其边上权重进行存储。那么存储的邻接矩阵实际上会存在大量的0。虽然可以通过稀疏表示等方式对稀疏性高的矩阵进行关键信息的存储,但是却增加了图存储的复杂性。

    因此,为了解决上述问题,一种可以只存储相连顶点关系的邻接表应运而生。

    邻接表

    在邻接表中,图的每一个顶点都是一个链表的头节点,其后连接着该顶点能够直接达到的相邻顶点。相较于无向图,有向图的情况更为复杂,因此这里采用有向图进行实例分析。

    在邻接表中,每一个顶点都对应着一条链表,链表中存储的是顶点能够达到的相邻顶点。存储的顺序可以按照顶点的编号顺序进行。比如上图中对于顶点B来说,其通过有向边可以到达顶点A和顶点E,那么其对应的邻接表中的顺序即B->A->E,其它顶点亦如此。

    通过邻接表可以获得从某个顶点出发能够到达的顶点,从而省去了对不相连顶点的存储空间。然而,这还不够。对于有向图而言,图中有效信息除了从顶点“指出去”的信息,还包括从别的顶点“指进来”的信息。这里的“指出去”和“指进来”可以用出度和入度来表示。

    入度:有向图的某个顶点作为终点的次数和。

    出度:有向图的某个顶点作为起点的次数和。

    由此看出,在对有向图进行表示时,邻接表只能求出图的出度,而无法求出入度。这个问题很好解决,那就是增加一个表用来存储能够到达某个顶点的相邻顶点。这个表称作逆邻接表。

    逆邻接表

    逆邻接表与邻接表结构类似,只不过图的顶点链接着能够到达该顶点的相邻顶点。也就是说,邻接表时顺着图中的箭头寻找相邻顶点,而逆邻接表时逆着图中的箭头寻找相邻顶点。

    邻接表和逆邻接表的共同使用下,就能够把一个完整的有向图结构进行表示。可以发现,邻接表和逆邻接表实际上有一部分数据时重合的,因此可以将两个表合二为一,从而得到了所谓的十字链表。

    十字链表

    十字链表似乎很简单,只需要通过相同的顶点分别链向以该顶点为终点和起点的相邻顶点即可。

    但这并不是最优的表示方式。虽然这样的方式共用了中间的顶点存储空间,但是邻接表和逆邻接表的链表节点中重复出现的顶点并没有得到重复利用,反而是进行了再次存储。因此,上图的表示方式还可以进行进一步优化。

    十字链表优化后,可通过扩展的顶点结构和边结构来进行正逆邻接表的存储:(下面的弧头可看作是边的箭头那端,弧尾可看作是边的圆点那端)

    data:用于存储该顶点中的数据;

    firstin指针:用于连接以当前顶点为弧头的其他顶点构成的链表,即从别的顶点指进来的顶点;

    firstout指针:用于连接以当前顶点为弧尾的其他顶点构成的链表,即从该顶点指出去的顶点;

    边结构通过存储两个顶点来确定一条边,同时通过分别代表这两个顶点的指针来与相邻顶点进行链接:

    tailvex:用于存储作为弧尾的顶点的编号;

    headvex:用于存储作为弧头的顶点的编号;

    headlink 指针:用于链接下一个存储作为弧头的顶点的节点;

    taillink 指针:用于链接下一个存储作为弧尾的顶点的节点;

    以上图为例子,对于顶点A而言,其作为起点能够到达顶点E。因此在邻接表中顶点A要通过边AE(即边04)指向顶点E,顶点A的firstout指针需要指向边04的tailvex。同时,从B出发能够到达A,所以在逆邻接表中顶点A要通过边AB(即边10)指向B,顶点A的firstin指针需要指向边10的弧头,即headlink指针。依次类推。

    十字链表采用了一种看起来比较繁乱的方式对边的方向性进行了表示,能够在尽可能降低存储空间的情况下增加指针保留顶点之间的方向性。具体的操作可能一时间不好弄懂,建议多看几次上图,弄清指针指向的意义,明白正向和逆向邻接表的表示。

     

     10  总结

    数据结构博大精深,没有高等数学的讳莫如深,也没有量子力学的玄乎其神,但是其在计算机科学的各个领域都具有强大的力量。本文试图采用图解的方式对九种数据结构进行理论上的介绍,但是其实这都是不够的。

    即便是简单的数组、栈、队列等结构,在实际使用以及底层实现上都会有许多优化设计以及使用技巧,这意味着还需要真正把它们灵活的用起来,才能够算是真正意义上的熟悉和精通。但是本文可以作为常见数据结构的一个总结,当你对某些结构有些淡忘的时候,不妨重新回来看看。

    ------------

    感兴趣可微信搜索【业余码农】,阅读更多技术干货!

    展开全文
  • sharepoint 2010 获取列表文件夹所有数据方法

    万次阅读 多人点赞 2012-12-24 15:28:40
    在sharepoint的数据列表查询中,一般都是采用CAML语言的方式来做查询,也就是平时我们用得比较多的是SPQuery.平时我们用对象模型splistitem,获取到的数据,都是列表根目录下的数据,而文件夹里面的数据,就没有包含...

    在sharepoint的数据列表查询中,一般都是采用CAML语言的方式来做查询,也就是平时我们用得比较多的是SPQuery.平时我们用对象模型splistitem,获取到的数据,都是列表根目录下的数据,而文件夹里面的数据,就没有包含进来,如果我们需要获取到文件夹里面的数据,以往我们都是一层层的去遍历,并且把数据添加到list中来,这种方式非常影响性能,效率也不高。

    在SPQuery中,有提供了一个方法,可以非常容易的获取到文件夹里面的数据,它有个Folder以及ViewAttributes属性,也就是我们下面方法的GetItems(SPList list)

    private void BindData()
            {
                SPWeb web = SPContext.Current.Web;
                SPList list = web.Lists["我的文档"];
                SPListItemCollection items = GetItems(list);
                GridView1.DataSource = items.GetDataTable();
                GridView1.DataBind();
            }
            private SPListItemCollection GetItems(SPList list)
            {
                SPQuery query = new SPQuery();
                query.Folder = list.RootFolder; ;
                query.ViewAttributes = "Scope=\"RecursiveAll\"";
                SPListItemCollection itemCollection = list.GetItems(query);
                return itemCollection;
            }

    广州京微信息科技有限公司,.微软sharepoint解决方案提供商。

    展开全文
  • 怎么把列表数据放到select里面

    千次阅读 2017-01-02 14:03:22
    我想把一串列表数据的一个字段放到jsp中下拉菜单里面,但是不知道怎么,这是部分代码 @RequestMapping(value = "/typelist") public String typelist(Model model) { List dictlist = dictService....
  • js实现提交前对列表数据的增删改查

    千次阅读 2016-09-02 22:56:59
    js实现列表数据的增删改查,AJAX提交js操作后数据最近工作中,有一处列表数据是页面初始化加载的,用户可以进行操作,因为这些数据并不存在数据库中,同时为了数据的整洁以及高效,所以要在页面进行增删改操作(其实...
  • mysql如何实现树状结构数据列表

    万次阅读 2020-11-04 17:04:18
    //查询此表的所有数据sql即可 expenseTypes = generateTree(expenseTypes); return RestResponse.success(expenseTypes); } private List<ExpenseType> generateTree(List<ExpenseType> expenseTypeList) { List...
  • Element ui下拉列表显示后台数据

    千次阅读 2019-11-27 11:06:15
    Element ui下拉列表显示后台数据 在写vue时,由于在很短时间内迅速要写出一个项目,所以基础知识掌握不是很牢固就开始上手,在下拉列表回显数据时就一直在搜索资料,以此写一篇文章记录。 el-select下拉框 <el...
  • 数据结构与算法三十题,懂这些面试就够了!

    万次阅读 多人点赞 2019-02-01 08:30:28
    由于数据结构用来以有组织的形式存储数据,而且数据是计算机科学中最重要的实体,因此数据结构的真正价值显而易见。 无论你解决什么问题,你都必须以这种或那种方式处理数据比如员工的工资,股票价格,购物清单,...
  • cocos creator学习16——滚动列表数据的动态加载

    万次阅读 热门讨论 2018-05-03 15:45:22
    //100项数据里面的起始数据记录索引 this.load_recode(this.start_index); }, 动态加载核心代码 于update(dt) 中持续调用 load_scroll_recode:function(){ //向下加载数据 //当开始位置比value_set的长度小则代表没...
  • 今天机房合作要数据库,然后我就用到了之前使用过的PowerDesigner 16.5 这个工具(专门用于数据库创建),然后把表好之后,想从概念模型生成物理模型,结果DBMS(数据库管理系统)列表始终不显示数据库信息。...
  • python_execel表格数据转化为列表list

    千次阅读 2020-03-27 11:36:01
    python_execel表格数据转化为列表list from pyecharts import options as opts from pyecharts.charts import Geo from pyecharts.globals import ChartType, SymbolType ​ # 导入数据 ​ # 湖北地区新增数据 ...
  • 例如:用户需要将不同行的数据,合并起来,显示于字段中的某个列。  例如:第一生产线生产:A,B产品;第二生产线生产:C、D产品,在数据库中的记录应为:  生产线 产品  1 A <br /
  • 各位大神,小弟最近需要数据列表,具体需求是从数据库中查询数据生成表格,这个数据时一行一行的。表格生成之后需要按照某一列的单元格内容进行分组,分组之后的数据可以折叠展开以方便查看(类似excel中行组合...
  • 每个应用程序都遵守沙盒机制,即程序仅能访问自身所属沙盒空间内的数据。 沙盒为程序主路径,包含以下目录:Document:存储用户自定义数据。 Library:存储应用程序相关数据。 tmp: 存放临时文件的地方,当iPhone...
  • 超硬核!数据结构学霸笔记,考试面试吹牛就靠它

    万次阅读 多人点赞 2021-03-26 11:11:21
    上次发操作系统笔记,很快浏览上万,这次数据结构比上次硬核的多哦,同样的会发超硬核代码,关注吧。
  • 现在想做的效果就是!... ... 数据是假装从后台拿回来的没有数量字段的json格式的数据。...自己写的这里,不想给testList数据加别的字段,假设数据很多此时把counter写成【0,0,0】这样的也不太合适所以…求大神指点一下
  • 本文代码实现基本按照《数据结构》课本目录顺序,外加大量的复杂算法实现,一篇文章足够。能换你一个收藏了吧?
  • 数据列表控件:WebForm 下的列表绑定控件基本就是GridView、DataList、Repeater;当然还有其它DropDownList、ListBox等。  它们的共同的设置数据源方法:XXX.DataSource=数据源。  那么这个数据源的格式,究竟有...
  • 大多数人刚上手 Vuex 的时候,首先都想知道,应该往其中存放什么样的数据呢?在对这个问题给出答案的过程中,很多人(包括我)先是来到了“一股脑放进去”的阶段。但是在遭遇了首次障碍后,你很快就会领悟到:这可...
  • MySql Oracle SqlServer三大数据库的数据类型列表   MySql数据类型   数据类型 描述 字节 推荐使用 SMALLINT 整数,从-32000到 +32000范围 2 存储相对...
  • elementui官方的数据是在data里写死的,如下: <template> <el-table ref="multipleTable" :data="tableData3" tooltip-effect="dark" style="width: 100%" @selection-change="handleSelectionChan....
  • 列表页 ====>点击跳转到列表详情页面 ======> 返回列表页(希望页面不重新加载,且保留原来浏览的位置)。 1.实现页面的不重新加载 使用vue的keep-alive <keep-alive>包裹动态组件时,会缓存不活动的组件...
  • 读入数据总结 前言 Android Studio中添加动态的数据库Database Inspector来可视化操作数据库 二、使用步骤 1.添加插件Database Inspector import numpy as np import pandas as pd import matplotlib.pyplot as plt...
  • 原因很弱智,data中没有初始化,却直接使用,第一次对List赋值时没问题,下拉框能够找到数据,改变List中的值后,下拉框中的值不会跟着List而改变,找了一大圈,发现没有对List在data中进行初始化。 ...
  • 在jsp页面加载时,从后台获取数据,动态生成下拉列表,加载完成之后,下拉列表中已经有值;
  • 很多个用户同时对n个题进行作答并得到结果,数据格式如下: 现在想通过一系列转换得到如下形式的数据框: 【Python实现】 操作之前,现将相关的包导入,如下: import numpy as np from pandas import ...
  • Python中的数据结构

    千次阅读 2020-06-17 14:00:52
    了解Python提供的不同数据结构,包括列表、元组等 介绍 数据结构听起来是一个非常直截了当的话题,但许多数据科学和分析的新手并不知道它是什么。当我询问这些人关于Python中不同的数据结构以及它们是如何工作的时...
  • 【筛选列表中最大值与最小值的差值】 喜欢可以关注【小猪课堂】公众号了解更多编程小技巧 f = lambda x : x . max ( ) - x . min ( ) frame . apply ( f ) 为什么axis=0的时候可以求列上的值呢?...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 74,060
精华内容 29,624
关键字:

列表数据怎么弄