• 算法框架之数组&链表&二叉树


    一、数据结构的存储方式

    1. 数据结构的基本存储方式 :【数组】(顺序存储)和【链表】(链式存储)

    但实际上朗朗上口的数据结构 还有很多 【栈】 【队列】 【散列表】但其实实际上都是基于 【数组/链表】实现的。

    下面举两个例子

      1.散列表:

        通过散列函数把键映射到一个大数组里。而且对于解决散列冲突的方法,拉链法需要链表特性,操作简单,但需要额外的空间存储指针;线性探查法就需要数组特性,以便连续寻址,不需要指针的存储空间,但操作稍微复杂些。

      2.栈/队列:

        这两种数据结构既可以使用链表也可以使用数组实现。用数组实现,就要处理扩容缩容的问题;用链表实现,没有这个问题,但需要更多的内存空间存储节点指针。

      3.堆/树:

        堆:可以被看做一棵完全二叉树的数组对象。

        树:用链表实现【衍生出各种巧妙的设计,比如二叉搜索树、AVL 树、红黑树、区间树、B 树等等,以应对不同的问题。】

      4.图:

        邻接表:链表实现。       邻接表比较节省空间,但是很多操作的效率上肯定比不过邻接矩阵。

        邻接矩阵:二维数组实现。 邻接矩阵判断连通性迅速,并可以进行矩阵运算解决一些问题,但是如果图比较稀疏的话很耗费空间。

    二、数据结构的基本操作

    1.对于任何数据结构,其基本操作无非遍历 + 访问,再具体一点就是:增删查改。

    2.各种数据结构的遍历 + 访问无非两种形式:线性的【迭代】和非线性的【递归】。

    三、数据结构操作的基本框架

    以下给出几种常见的遍历操作方式

    1. 数组遍历框架,典型的线性迭代结构:

    /**
    * @param {number[]} arr
    */
    function go(arr) {
        for (var i = 0; i < arr.length; i++) {
            // 迭代访问 arr[i]
        }
    }

    2. 链表遍历框架,兼具迭代和递归结构:

    /**
     * Definition for ListNode.
     * function ListNode (val) {
     *     this.val = val;
     *     this.next= null;
     * }
     */
    /**
     * @param {ListNode } head
     */
     //go1迭代
    function go1(head) {
    //方式一 for循环
        for (let p = head; p != null; p = p.next) {
            // 迭代访问 p.val 【迭代操作】
        }
    //方式二 while循环
        while(head){
           // 迭代访问 head.val 【迭代操作】
            head=head.next
        }
    }
     //go2递归
    function go2(head) {
        // 递归访问 head.val 【迭代操作】
        go2(head.next)
    }

    3. 二叉树遍历框架,典型的非线性递归遍历结构:【扩展 树的遍历】

    /**
     * Definition for a binary tree node.
     * function TreeNode(val) {
     *     this.val = val;
     *     this.left = this.right = null;
     * }
     */
    
    function go(root) {
    //递归时 操作可在任意位置放置
    //例如【前、中、后序 遍历】 只需分别将root.val 放于递归操作 前 中 后即可
    
       //root.val 【前序遍历】
        go(root.left)
       //root.val 【中序遍历】
        go(root.right)
       //root.val 【后序遍历】
    }

    3.1 由上面看出N叉树遍历 只需按照子节点顺序遍历即可

    /**
     * Definition for a tree node.
     * function Node(val,children) {
     *    this.val = val;
     *    this.children = children;
     * };
     */
    /**
     * @param {Node} root
     */
    function go(root) {
    //递归时 操作可在任意位置放置
    
        for(let i of root.children)
            go(i)
    }
  • 相关阅读:
    安卓面试人人面向源码开发(一)
    Kotlin常见用法
    安卓触摸事件调度顺序
    自定义view 可自动换行滑动的LinearLayout
    屏幕适配那些事一篇带你搞定,出发与结论点独特适合新手。欢迎收藏
    初识位域
    简单区分Vmware的三种网络连接模式(bridged、NAT、host-only)
    刚开始学Python,坚持下去
    FAT AP 与 FIT AP的特点和区别
    BSSID,SSID,ESSID区别
  • 原文地址:https://www.cnblogs.com/cc123nice/p/12811238.html
Copyright © 2020-2023  润新知