您的位置:首页 > 理论基础 > 数据结构算法

JavaScript数据结构与算法学习总结--链表

2016-07-14 17:11 429 查看
    数据结构与算法这个内容很多人一听都会觉得头大,我在最开始接触到的时候也是云里雾里。因为大一刚学编程的时候,一直连入门都如不进去,导致后来学习数据结构和算法也提不起兴趣。直到开始接触Web前端,学习了JavaScript这门脚本语言,便想学习一些基于JS的数据结构与算法知识,并且记录下来。

 一、概述   

数据结构分为线性结构与非线性结构,我觉得线性结构相对于非线性结构更好理解一些。而在线性结构中,链表属于相对较复杂的一种数据结构。

    我们先简要提一下数组。数组是最简单最基本的结构,其每一个元素在内存中连续存放。我们可以通过数组下标index任意取得自己想要的元素。

    不同于数组,链表中的元素在内存中不连续存放,这点非常重要。虽然其存放并不连续,链表中的每一个节点也有迹可循,即每个节点是和其前一个节点直接相连的。因此,我们要取得链表中的任意一个节点,必须通过从链表的第一个元素开始依此查找,直到找到我们所需要的节点。这就像是我们要爬到山顶但没有地图,我们需要从起始点开始,根据路标来找到下一个地点,最终到达目的地。

    链表的几个特点:

    1. 链表元素在内存中不连续存放

    2. 链表的最后一个节点始终指向null

    下面来说说JS中的链表创建。JS是一种基于对象的语言。在JS中,我们描述链表中的节点,需要指明一个节点对象node,这个节点包含两部分:节点的内容element和它指向下一个节点的指针next:

     


所以一个链表就是这样:

      


二、链表结构的JavaScript描述  
 

接下来利用JS对链表进行描述:

我们先初始化一个链表:

<span style="font-size:14px;"><span style="font-size:12px;">function LinkedList() {
var Node = function (element) {
this.element = element;
this.next = null; // 初始化 next指针为 null
};
var length = 0;  // 初始化 长度为0
var head = null; // 初始化 链表头为null
}</span></span>

主要包括:一个节点对象,初始化链表长度为0;初始化表头为null。因为对链表的任何操作都要从表头开始,所以表头的定义很重要!

好了,接下来我们要为这个链表添加一些方法。链表常用的方法主要包括:

1、向链表尾部添加一个节点 append(element)

<span style="font-size:14px;"><span style="font-size:12px;">// append方法 在最后一位添加元素
this.append = function (element) {
var node = new Node(element);
var current;  // current为当前所指的节点,遍历时从head开始
if (head === null) { // 如果是空链表,将node设置为链表头
head = node;
} else {
current = head;  // 从head开始遍历
while (current.next) {
current = current.next;
}
current.next = node; // 遍历到最后一个节点时,current指向最后一个节点,此时将其next指向要添加的node即可
}
length++; // 添加后记得链表长度加1
};</span></span>

    步骤:

     (1)初始化一个节点对象,初始化一个变量储存当前元素

     (2)判断链表是否为空。若为空,则将待添加的节点设置为表头

     (3)若非空,从head开始遍历,直到current.next为null,说明current遍历到了最后一个节点

     (4)将current.next指向node

     (5)链表长度length+1

2、移除指定位置节点 removeAt(position)

<span style="font-size:14px;"><span style="font-size:12px;">// removeAt 移除指定位置元素,并返回被移除的元素(对于最后一个元素不用特殊对待,依旧遵循此方法)
this.removeAt = function (position) {
if(position<0 || position>=length){ // 若位置索引不存在 返回null
return null;
}else{
var current = head;
var previous;
var index = 0;
if(position == 0){  // 删除第一个元素
head = current.next;
}else{
while(index < position){
previous = current;
current = current.next;
index++;
}
previous.next = current.next;
}
length--;
return current.element;  // 记住,current只是承载这个节点的容器,element才是需要返回的内容!
}
};</span></span>

    步骤:

     (1)判断所删除的下标是否在链表范围内

     (2)若无此下标,返回null

     (3)若有此下标,初始化current为head,表示当前遍历指向;初始化previous,用来存储当前节点的前一个节点;初始化index为0,表示当前下标

     (4)若要删除的为第一个节点,直接将current.next赋值给head

     (5)若不是第一个节点,while循环遍历到要删除的位置,将current.next指向previous.next,就删除了当前元素。被删除元素被回收

     (6)返回被删除元素,链表长度length-1

3、在任意位置插入元素 insert(position,element)
<span style="font-size:14px;"><span style="font-size:12px;">// insert方法 在任意位置插入元素
this.insert = function(position,element){
if(position<0 || position>=length){
return false;
}else{
var node = new Node(element); // 因为是插入节点,所以要先新建一个Node对象~
var current = head; // 初始化 current 指向 head
var previous;
var index = 0;
if(position == 0){  // 书上这里是 position===0,这里为什么要用===不是很明白。有读者理解的话可以告诉我哦~
node.next = current; // 一定要先将current的值赋给node.next。如果先将node给head,current就变成了node,会出错
head = node;
}else{
while(index<position){ // while循环,不停地向后移直到要插入的地方
previous = current;
current = current.next;
index++;
}// 循环结束时,current为当前要插入位置上的节点
node.next = current; // 将当前位置上的节点赋给node.next
previous.next = node; // 让previous.next 指向node(原本指向的是current)
}
length++;
return true; // 插入成功
}
};</sp
a153
an></span>
 
步骤:
       (1)判断所要插入的下标是否在链表范围内

       (2)若无此下标,返回null

       (3)若有此下标,初始化一个node节点;初始化current为head,表示当前遍历指向;

                 初始化previous,用来存储当前节点的前一个节点;初始化index为0,表示当前下标

       (4)若要插入的为第一个位置,直接将current赋值给node.next,再将node赋值给head

       (5)若不是第一个位置,while循环遍历到要添加的位置,将node.next指向current节点,再让previous.next指向node,就插入了新元素

       (6)链表长度length+1,返回true

以上就是链表中比较重要的几个方法啦~

除了这些,还有一些比较常用的也很好理解的方法:

indexOf(element):查找某元素在链表中的位置

remove(element):删除某元素(不同于removeAt已知元素下标,这个是已知元素内容)

isEmpty:判断是否为空

size:链表大小(长度)

toString:将链表内容转化为字符串便于输出

下面我们来展示这些方法JavaScript实现:

// indexOf 查找某元素下标
this.indexOf = function(element){
var current = head;
var index = 0;
while(current){
if(current.element == element){
return index
}
current = current.next;
index++;
}
return '-1'; // 如果遍历完了还找不到此元素,返回-1
};
// remove 已知某节点内容,找到并删除他它
this.remove = function(element){
var index = this.indexOf(element);
return this.removeAt(index); // 若没有此元素则index为-1,返回false
};
// isEmpty 判断是否为空
this.isEmpty = function(){
return length===0;
};
// size返回链表长度
this.size = function(){
return length;
};
// toString方法,转换为字符串
this.toString = function(){
var current = head;
var string = '';  // 初始化一个空string便于存放
while(current){
string = current.element;
current = current.next;
}
return string;
};


【参考资料】《学习JavaScript数据结构与算法》中文版
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 数据结构