学习JavaScript数据结构与算法(四)——链表
来源:互联网 发布:矩阵怎么计算 编辑:程序博客网 时间:2024/06/08 21:59
链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。
每个元素由一个存储元素本身的节点和指向下一个元素的引用(也称指针或链接)组成。
相比较与传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。
特别需要注意的是,链表需要使用指针。
对于数组而言,可以直接访问任何位置的任何元素;而要想访问链表中的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素。
在现实生活中,也有一些链表的例子。
举个例子,一群人手拉手站成一排,每个人是一个元素,手就是链向下一个人的指针。可以向队列中增加人,只需要找到想加入的点,断开连接,插入一个人在重新连接起来。
再比如火车,一列火车是由一节节车厢组成的,每节车厢都相互连接。每节车厢都是列表的元素,车厢间的连接就是指针。
再举个例子,寻宝游戏。你有一条线索,这条线索是指向下一个线索的地点的指针。你顺着这条线索去寻找下一个线索。得到中间的线索的唯一方法就是,从第一条线索开始顺着列表寻找。
创建链表
先建立骨架,如下所示。
function LinkedList () { /* Node辅助类,表示要加入列表的项。 包含一个element属性,即要添加到列表的值,以及一个next属性,即指向列表中下一个节点项的指针。 */ var Node = function(element){ this.element = element; this.next -= null; }; var length = 0;//存储列表项的数量的length属性 var head = null;//存储第一个节点的引用 /* append(element) 向列表尾部添加一个新的项 */ this.append = function(element){}; /* insert(position, element) 向列表的特定位置插入一个新的项 */ this.insert = function(position, element){}; /* removeAt(position) 从列表的特定位置移除一项 */ this.removeAt = function(position){}; /* remove(element) 从列表中移除一项 */ this.remove = function(element){}; /* indexOf(element) 返回元素在列表中的索引 如果列表中没有该元素则返回-1 */ this.indexOf = function(element){}; /* isEmpty() 如果链表中不包含任何元素,返回true 如果链表长度大于0则返回false */ this.isEmpty = function(){}; /* size() 返回链表包含的元素个数 与数组的length属性类似 */ this.size = function(){}; /* getHead() 获取第一个元素 */ this.getHead = function(){}; /* toString() 把LinkedList对象转换成一个字符串 */ this.toString = function(){}; this.print = function(){};}
接下来,实现上述代码中的那些方法。
1、向链表尾部追加元素——append()
可能出现两种情况:一是列表为空,添加的是第一个元素;二是列表不为空,向其追加元素。
this.append = function(element){ var node = new Node(element), current; //向为空的列表添加一个元素 if (head == null) { head = node; } //向不为空的列表尾部添加元素 else { current = head; //循环列表,直到找到最后一项 //列表最后一个节点的下一个元素始终是null while (current.next) { current = current.next; } //找到最后一项,将其next赋为node,建立链接 current.next = node; } length++;//更新列表的长度};
2、根据给定位置从链表中移除元素——removeAt()
可能出现两种情况:一是移除第一个元素,二是移除第一个元素之外的元素。
this.removeAt = function(position){ //检查越界值,验证这个位置是否有效 //从0(包括0)到列表的长度(size-1)都是有效的位置 if (position > -1 && position < length) { var current = head, previous, index = 0; //移除第一项 if (position === 0) { head = current.next; } else { while (index++ < position) { previous = current; current = current.next; } /* current是对要移除元素的引用 previous是对要移除元素的前一个元素的引用 要移除current,只需将previous与current的下一项链接起来 */ previous.next = current.next; } length--; return current.element; } //不是有效位置,返回null else { return null; }};
3、在任意位置插入一个元素——insert()
this.insert = function(position, element){ //检查越界值 if (position >= 0 && position <= length) { var node = new Node(element), current = head, previous, index = 0; //在列表的起点添加一个元素 if (position === 0) { node.next = current; head = node; } //在列表中间或尾部添加一个元素 else { while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; } length++;//更新列表长度 return true; } //越界就返回false,表示没有添加项到列表中 else { return false; }};
4、其他方法的实现
this.toString = function(){ var current = head, string = ''; while (current) { string = current.element + (current.next ? ', ' : ''); current = current.next; } return string;};this.indexOf = function(element){ var current = head, index = 0; while (current) { if (element === current.element) { return index; } index++; current = current.next;//检查列表中下一个节点 } return -1;};this.remove = function(element){ var index = this.indexOf(element); return this.removeAt(index);};this.isEmpty = function(){ return length === 0;};this.size = function(){ return length;//列表的length是内部控制的,因为LinkedList是从头构建的};this.getHead = function(){ return head;//head为私有变量,不能在LinkedList实例外部被访问和更改,只有通过LinkedList实例才可以};this.print = function(){ console.log(this.toString());};
测试代码如下:
var list = new LinkedList();list.append(15);list.print(); //输出15console.log(list.indexOf(15)); //输出0list.append(10);list.print(); //输出15, 10console.log(list.indexOf(10)); //输出1list.append(13);list.print(); //输出15, 10, 13console.log(list.indexOf(13)); //输出2console.log(list.indexOf(10)); //输出1list.append(11);list.append(12);list.print(); //输出15, 10, 13, 11, 12console.log(list.removeAt(1)); //输出10list.print() //输出15, 13, 11, 12console.log(list.removeAt(3)); //输出12list.print(); //输出15, 13, 11list.insert(0,16);list.print(); //输出16, 15, 13, 11list.insert(1,17);list.print(); //输出16, 17, 15, 13, 11list.insert(list.size(),18);list.print(); //输出16, 17, 15, 13, 11, 18list.remove(16);list.print(); //输出17, 15, 13, 11, 18list.remove(11);list.print(); //输出17, 15, 13, 18
在控制台显示的结果如下:
阅读全文
0 0
- 学习JavaScript数据结构与算法(四)——链表
- 学习JavaScript数据结构与算法(四)——双向链表
- 学习JavaScript数据结构与算法(四)——循环链表
- 学习JavaScript数据结构与算法(一)——数组
- 学习JavaScript数据结构与算法(二)——栈
- 学习JavaScript数据结构与算法(三)——队列
- 学习JavaScript数据结构与算法(五)——集合
- 学习JavaScript数据结构与算法(六)——字典
- JavaScript数据结构与算法学习总结--链表
- 学习javascript数据结构(四)——树
- 数据结构与算法javascript描述(四) 冒泡排序
- 数据结构与算法Javascript描述(四)双向链表
- 数据结构与算法JavaScript (四) :串(BF)
- 数据结构与算法(四)链表
- 学习JavaScript数据结构与算法(七)——散列表(一)
- 学习JavaScript数据结构与算法(七)——散列表(二)
- 前端学习总结(二十二)——常见数据结构与算法javascript实现
- 学习JavaScript数据结构与算法(八)——二叉树
- LDA 主题模型
- Codeforces Round #439 (Div. 2) E. The Untended Antiquity (hash+数状数组)
- JAVA课堂练习
- FTPrep, 108 Convert Sorted Array to Binary Search Tree
- EU5-12:Talking about the future technology
- 学习JavaScript数据结构与算法(四)——链表
- Codeforces Round #439 (Div. 2)-The Intriguing Obsession(DP)
- JAVA提高篇(18)--BufferedReader、BufferedWriter
- FTPrep, 109 Convert Sorted List to Binary Search Tree
- Ubuntu16.04 安装百度云bcloud
- python邮件SMTP的GUI编程
- bootstrap的简单实用
- sudo给某些用户添加以root权限运行某些命令
- PTA 2.3