JS实现线性表的链式表示方法示例【经典数据结构】

所属分类: 网络编程 / JavaScript 阅读数: 529
收藏 0 赞 0 分享

本文实例讲述了JS实现线性表的链式表示方法。分享给大家供大家参考,具体如下:

从上一节可以,顺序存储结构的弱点就是在插入或删除操作时,需要移动大量元素。所以这里需要介绍一下链式存储结构,由于它不要求逻辑上相邻的元素在物理位置上也相邻,所以它没有顺序存储结构的弱点,但是也没有顺序表可随机存取的优点。

下面介绍一下什么是链表

线性表的链式存储结构用一组任意的存储单元存储线性表的数据元素。所以,每一个数据元素除了存储自身的信息之外,还需要存储一个指向其后继的存储位置的信息。这两部分信息组成了元素的存储映像,称为结点

结点包括两个域:数据域指针域

数据域是元素中存储数据元素的信息。

指针域是元素中存储的后继存储位置的信息。

n个结点链接成为链表,就是线性表的链式存储结构,又由于此链表的每个结点中只包含一个指针域,所有又称为线性链表或单链表

举一个例子

上图表示的线性表为

ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG

这样应该就好理解多了吧。

下面我们通过js代码来实现链表的插入和删除还有查找操作

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<script type = "text/javascript">
 var Node = function(newData){//创建节点对象
 this.next = null;
 this.data = null;
 this.Init = function(){
  this.data = newData;
 };
 this.Init();
 }
 //定义链表类
 var List = function(){
 this.head = null;
 this.size = 0;
 this.Init = function(){
  this.head = null;
  this.size = 0;
 }
 this.Init();
 this.Insert = function(newData){//初始批量插入操作
  this.size += 1;
  var newNode = new Node(newData);
  if(this.head == null){
  this.head = newNode;
  return;
  }
  var tempNode = this.head;
  while(tempNode.next != null)
  tempNode = tempNode.next;//找到链表尾部
  tempNode.next = newNode;//将新元素插入到链表尾部
 };
 this.GetData = function(pos){//查找操作
  if(pos >= this.size || pos < 0)
  return null;
  else{
  tempNode = this.head;
  for(i = 0;i < pos;i++)
   tempNode = tempNode.next; //找到所处位置
  return tempNode.data;
  }
 };
 this.Remove = function(pos){//移除某一位置节点
  if(pos >= this.size || pos < 0)
  return null;
  this.size -= 1;
  tempNode = this.head;
  if(pos == 0){
  this.head = this.head.next;
  return this.head;
  }
  for(i = 0;i < pos - 1;i++){
  tempNode = tempNode.next;
  }
  tempNode.next = tempNode.next.next;
  return tempNode.next;
 };
 this.InsertBefore=function(data,pos){//从某一位置前插入节点
  if(pos>=this.size||pos<0)
  return null;
  this.size+=1;
  tempNode=this.head;
  var newNode = new Node(data);//将数据创造节点
  if(pos==0){
  newNode.next=tempNode;
  return newNode.next;
  }
  for(i=0;i<pos-1;i++){
  tempNode=tempNode.next;//找到插入的位置
  }
  newNode.next=tempNode.next;//插入操作
  tempNode.next=newNode;
  return newNode.next;
 };
 this.Print = function(){//输出
  document.write("链表中元素: <br>");
  tempNode = this.head;
  while(tempNode != null){
  document.write(tempNode.data + " ");
  tempNode = tempNode.next;
  }
  document.write("<br>");
 };
 };
 //运行测试:
 var list = new List();
 var array = new Array(1,2,3,4,5,6);
 for(i = 0;i < array.length;i++){
 list.Insert(array[i]);
 }
 list.Print();
 document.write("查找操作下标为4的元素: <br>");
 var data= list.GetData(4);
 document.write(data+"<br>");
 document.write("删除操作: <br>");
 list.Remove(5);
 list.Print();
 document.write("插入操作: <br>");
 list.InsertBefore(8,3);
 list.Print();
 document.write("链表大小: " + list.size);
</script>
</head>
<body>
</body>
</html>

运行得到结果为

先分析一下插入和删除的代码。

 this.InsertBefore=function(data,pos){//从某一位置前插入节点
  if(pos>=this.size||pos<0)
    return null;
  this.size+=1;
  tempNode=this.head;
  var newNode = new Node(data);//将数据创造节点
  if(pos==0){
    newNode.next=tempNode;
    return newNode.next;
  }
  for(i=0;i<pos-1;i++){
    tempNode=tempNode.next;//找到插入的位置
  }
    newNode.next=tempNode.next;//插入操作
    tempNode.next=newNode;
  return newNode.next;
};
this.Remove = function(pos){//移除某一位置节点
      if(pos >= this.size || pos < 0)
       return null;
      this.size -= 1;
      tempNode = this.head;
      if(pos == 0){
       this.head = this.head.next;
       return this.head;
      }
      for(i = 0;i < pos - 1;i++){
       tempNode = tempNode.next;
      }
      tempNode.next = tempNode.next.next;
      return tempNode.next;
};

可以看出,插入和删除的世界复杂度都为o(n)。因为在第i个结点前插入或删除都得找到第i-1个元素。

再来看看初始化方法Insert,

this.Insert = function(newData){//初始批量插入操作
      this.size+= 1;
      var newNode = new Node(newData);
      if(this.head == null){
       this.head = newNode;
       return;
      }
      var tempNode = this.head;
      while(tempNode.next != null)
       tempNode = tempNode.next;//找到链表尾部
      tempNode.next= newNode;//将新元素插入到链表尾部
};

初始的插入Insert方法的时间复杂度也是o(n)。

下面介绍一下另外一种形式的链式存储结构,就是循环链表。它的特点就表中的最后一个结点的指针域指向头结点,整个链表形成一个环。有时候,在循环链表中设立尾指针而不设立头指针,可以简化操作。比如两个线性表集合为一个表时,仅需将一个表的表尾和另一个表的表头相接。这个操作的时间复杂度是o(1)。

如下图所示

上面介绍的链表只能通过某个结点出发寻找后面的结点。也就是说在单链表中,寻找下一结点的时间复杂度为o(1),而寻找上一结点的时间复杂度为o(n)。为了克服单链表这种单向性的缺点,可以利用双向链表

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript数据结构与算法技巧总结》、《JavaScript数学运算用法总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结

希望本文所述对大家JavaScript程序设计有所帮助。

更多精彩内容其他人还在看

Angular使用Md5加密的解决方法

这篇文章主要介绍了Angular使用Md5加密的解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解JS构造函数中this和return

本文通过实例代码给大家介绍了JS构造函数中this和return,需要的朋友参考下吧
收藏 0 赞 0 分享

ES6中Array.find()和findIndex()函数的用法详解

ES6为Array增加了find(),findIndex函数。find()函数用来查找目标元素,找到就返回该元素,找不到返回undefined,而findIndex()函数也是查找目标元素,找到就返回元素的位置,找不到就返回-1。下面通过实例详解,需要的朋友参考下吧
收藏 0 赞 0 分享

JS闭包的几种常见形式实例详解

本文通过实例代码给大家详细介绍了js闭包的几种常见形式,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友参考下
收藏 0 赞 0 分享

ES6中Array.copyWithin()函数的用法实例详解

ES6为Array增加了copyWithin函数,用于操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置上去。下面重点给大家介绍ES6中Array.copyWithin()函数的用法,需要的朋友参考下
收藏 0 赞 0 分享

Javascript 严格模式use strict详解

严格模式:由ECMA-262规范定义的JavaScript标准,对javascrip的限制更强。这篇文章主要介绍了Javascript 严格模式use strict详解 ,需要的朋友可以参考下
收藏 0 赞 0 分享

引入JavaScript时alert弹出框显示中文乱码问题

今天在HTML中引入JavaScript文件运行时,alert弹出的提示框中文显示为乱码,怎么解决此问题呢?下面小编给大家带来了引入JavaScript时alert弹出框显示中文乱码问题的解决方法,一起看看吧
收藏 0 赞 0 分享

AngularJs 延时器、计时器实例代码

这篇文章主要介绍了AngularJs 延时器、计时器实例代码,需要的朋友可以参考下
收藏 0 赞 0 分享

JS分页的实现(同步与异步)

这篇文章主要介绍了JS分页的实现(同步与异步),需要的朋友可以参考下
收藏 0 赞 0 分享

Angularjs自定义指令实现分页插件(DEMO)

由于最近的一个项目使用的是angularjs1.0的版本,涉及到分页查询数据的功能,后来自己就用自定义指令实现了该功能,下面小编把实例demo分享到脚本之家平台,需要的朋友参考下
收藏 0 赞 0 分享
查看更多