zoukankan      html  css  js  c++  java
  • javascript linkedlist data structures

    在使用C++的时候我们经常会使用到各种容器,这些容器其实就是一种数据结构。在java中其实也是如此。但是由于javascript只给我们提供了一种内置的数据结构数组,准备来说是对象。没有我们常见的那些数据结构,但是在实际的工作中我们却不能离开这些常见的数据结构。所以我们只能去自己构造了。

    虽然javascript中的数组的操作,比C++/java等操作数组方便的多,但是毕竟数组是一种对象,在对数据进行处理的时候效率还是很低的。所以有时候我们要自己构造想要的数据结构了。

    定义(define):

    链表是有一组节点组成的集合。每个节点都包含两部分:第一部分是存储数据元素的数据域,另一个是存储下一个结点地址的引用域。每个节点都会使用一个对象的引用来指向他的后继节点。这个对后继对象的引用就是我们常说的链。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。因此在除了对数据元素的随机访问使用数组外,其他情况下在使用一位数组的地方,都可以使用链表。

     我们知道数组主要是靠位置来进行引用元素的,而链表则是通过彼此之间的关系来引用的。在我们想查找一个再链表中的元素的时候,我们就必须从链表头开始遍历查找。然而在标示链表头的时候确实有些麻烦,利用javascript的灵活性,我想我们还是很容易就解决的。从上图中我们也看到最后一个元素的引用应该设置为null。由于在链表中插入禾删除元素,只需要改变自身元素与相邻元素的引用就可以了,不必像数组那样移动元素的位置,这样看起来效率会高一点。

    构建链表(construct linked list):

     我们设计的这个链表是一个基于对象的链表,包括两个类:Node类用来表示节点,LinkedList类用来提供插入节点,删除节点,查询节点元素个数。。等一些列操作。

    Node类:

    function Node (element){
          this.element = element;
          this.next = null;
      }

    Node类包含两个属性,element用来保存节点的元素,next用来保存指向下一个节点的链接。head节点的next属性我们暂且设置为null,当有数据插入的时候我们在设置head的next属性指向这个新元素。

    LinkedList类:

    LinkedList类和Node类一样也是一个构造函数,但LinkListed类只有一个属性,那就是使用一个Node节点来保存该链表的头节点。

    <html>
    <head>
        <title>Date Example</title>
    </head>
    <body>
    <div id="content"></div>
    <input type="button" value="Set InnerHTML" onclick="testDate()">
    
    <script type="text/javascript">
    
      //   Node construct
      function Node (element){
          this.element = element;
          this.next = null;
      }
       
       //   LinkedList construct
      function LinkedList (){
          this.head = new Node("head");
    
          //   遍历链表查找给定的数据(我们要把数据插入到那个节点的后面)
          this.find = function (item){
           var currNode = this.head;
           while (currNode.element != item){
                  currNode = currNode.next;
           }
    
           return currNode
          };
    
          //   向链表中插入一个节点
          this.insert = function (newElem, item){
           var newNode = new Node(newElem);
           var current = this.find(item);
           newNode.next = current.next;
           current.next = newNode;
          };
        
        //   查询前一个节点
          this.findPrevious = function (item){
           var currNode = this.head;
           while ((currNode.next != null) && (currNode.next.element != item)){
                 currNode = currNode.next;
           }
           return currNode;
          };
    
          //   删除某个节点 
          this.remove = function (item){
           var prevNode = this.findPrevious(item);
           if (prevNode.next != null){
               
               prevNode.next = prevNode.next.next;
           }
          };
    
          //   显示列表中的节点
          this.display = function (){
           var currNode = this.head;
           while (currNode.next != null){
               console.log("current Node is:" + currNode.next.element);
               currNode = currNode.next;
           } 
          };
    
      }
    </script>
    </body>
    </html>

    上面就是一个比较构造一个普通链表的方式。里面包含了基本的链表操作方法。

    var cities = new LinkedList();
      cities.insert("shang", "head");
      cities.insert("hai", "shang");
      cities.insert("shan", "hai");
      cities.insert("xi", "shan");
      cities.display();

    在浏览器的Cnsole中查看结果。

     链表在日常 使用中还有双向链表,循环链表。。。

    首先来看一下双向链表吧:

    在上面创建的链表中我们只能从链表的头遍历到链表的尾,二双向链表让我们既能从链表的头遍历到尾,也能让我们从尾遍历到头。其实很简单,我们在每个节点中增加一个属性,这个属性指向前驱节点的链接,这样只是给插入与删除节点多添加一些代码罢了。如图:

    展示了双向链表的工作原理。

    <html>
    <head>
        <title>Date Example</title>
    </head>
    <body>
    <div id="content"></div>
    <input type="button" value="Set InnerHTML" onclick="testDate()">
    
    <script type="text/javascript">
    
      //   Node construct
      function Node (element){
          this.element = element;
          this.next = null;
        this.previous = null;
    
      }
       
       //   LinkedList construct
      function LinkedList (){
          this.head = new Node("head");
    
          //   遍历链表查找给定的数据(我们要把数据插入到那个节点的后面)
          this.find = function (item){
           var currNode = this.head;
           while (currNode.element != item){
                  currNode = currNode.next;
           }
    
           return currNode
          };
    
          //   向链表中插入一个节点
          this.insert = function (newElem, item){
           var newNode = new Node(newElem);
           var current = this.find(item);
           newNode.next = current.next;
           newNode.previous = current;
           current.next = newNode;
          };
    
        //   查找最后一个节点(便于我们从后往前遍历)  
        this.findLast = function (){
            var lastNode = this.head;
            while (lastNode.next != null){
                 lastNode = lastNode.next;
            }
    
            return lastNode;
        };
        
        //   反序显示双向列表中的元素
        this.displayReverse = function (){
           var currNode = this.head;
           currNode = this.findLast();
           while (currNode.previous != null){
              console.log("current Node is:" + currNode);
              currNode = currNode.previous;
           }
        };
    
          //   删除某个节点 
          this.remove = function (item){
           var crrNode = this.find(item);
           if (crrNode.next != null){
               
               currNode.previous.next = currNode.next;
               currNode.next.previous = currNode.preious;
               currNode.previous = null;
               currNode.next = null;
           }
          };
    
          //   显示列表中的节点
          this.display = function (){
           var currNode = this.head;
           while (currNode.next != null){
               console.log("current Node is:" + currNode.next.element);
               currNode = currNode.next;
           } 
          };
    
    
    
      }
    
      var cities = new LinkedList();
      cities.insert("shang", "head");
      cities.insert("hai", "shang");
      cities.insert("shan", "hai");
      cities.insert("xi", "shan");
      cities.display();
      
    </script>
    </body>
    </html>

    循环列表:

    循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的引用指向头节点,整个链表形成一个环

    从链表的尾部向后移动,将会从新遍历这个链表。

    <html>
    <head>
        <title>Date Example</title>
    </head>
    <body>
    <div id="content"></div>
    <input type="button" value="Set InnerHTML" onclick="testDate()">
    
    <script type="text/javascript">
    
      //   Node construct
      function Node (element){
          this.element = element;
          this.next = null;
      }
       
       //   LinkedList construct
      function LinkedList (){
          this.head = new Node("head");
        this.head.next = this.head;
    
          //   遍历链表查找给定的数据(我们要把数据插入到那个节点的后面)
          this.find = function (item){
           var currNode = this.head;
           while ((currNode.element != item) && (currNode.next.element != "head")){
                  currNode = currNode.next;
           }
    
           return currNode
          };
    
          //   向链表中插入一个节点
          this.insert = function (newElem, item){
           var newNode = new Node(newElem);
           var current = this.find(item);
           newNode.next = current.next;
           current.next = newNode;
          };
        
        //   查询前一个节点
          this.findPrevious = function (item){
           var currNode = this.head;
           while ((currNode.next != null) && (currNode.next.element != item) && (currNode.next.element != "head")){
                 currNode = currNode.next;
           }
           return currNode;
          };
    
          //   删除某个节点 
          this.remove = function (item){
           var prevNode = this.findPrevious(item);
           if (prevNode.next != null){
               
               prevNode.next = prevNode.next.next;
           }
          };
    
          //   显示列表中的节点
          this.display = function (){
           var currNode = this.head;
           while ((currNode.next != null) && (currNode.next.element != "head")){
               console.log("current Node is:" + currNode.next.element);
               currNode = currNode.next;
           } 
          };
    
      }
    
      var cities = new LinkedList();
      cities.insert("shang", "head");
      cities.insert("hai", "shang");
      cities.insert("shan", "hai");
      cities.insert("xi", "shan");
      cities.display();
      
    </script>
    </body>
    </html>

    当我们在使用循环链表的时候,注意不要使程序陷入死循环。。。在以前这些方法的基础上我们还可以编写更多的方法,来简化我们的使用和操作。

  • 相关阅读:
    实习第一周小记------生活不易
    第一次实习面试感受----苦逼程序员生活初体验
    第一次实习面试感受----苦逼程序员生活初体验 分类: 程序人生 2013-07-28 14:13 2395人阅读 评论(0) 收藏
    Java-基于JDK的动态代理
    JS字符串去替换元素再转换成数组
    byte溢出栗子
    Java链式写法
    Scala笔记
    Java反射使用方法
    Java数组3种创建方式
  • 原文地址:https://www.cnblogs.com/duhuo/p/5079793.html
Copyright © 2011-2022 走看看