单链表
线性表的链式存储,包含两个域,一个存储的值(this.data),一个指向下一个链表节点(this.next)。
封装链表类,添加链表的属性:链表节点、头部(链表的起始点)、长度。
// 封装链表类
function LinkedList() {
// 内部的类:节点类
function Node(data) {
this.data = data;
this.next = null;
}
//指向链表头部的属性
this.head = null
//记录链表长度的属性
this.length = 0;
}
给链表添加方法进行增删改查等操作。
1.添加节点append
LinkedList.prototype.append = function(data) {
//1.创建新节点
var newNode = new Node(data);
//2.判断是否存在第一个节点
//2.1 不存在第一个节点
if(this.length == 0) {
this.head = newNode;
} else {
// 2.2 存在第一个节点,找到最后一个节点赋值
// current即为链表的指针
var current = this.head;
while(current.next) {
current = current.next;
}
// 最后节点的next指向新节点
current.next = newNode;
}
// 长度属性加一
this.length += 1;
}
2.tostring()
LinkedList.prototype.toString = function() {
// 指针current,存储结果tostring
var current = this.head;
var listString = '';
// 遍历链表
while(current) {
listString += current.data + ' ';
current = current.next;
}
return listString;
}
3.在确定位置position插入节点
LinkedList.prototype.insert = function(position, data) {
//1.判断是否超出本身链表长度 或 小于0
if(position < 0 || position > this.length) return false;
//2.创建新插入节点
var newNode = new Node(data);
//3.插入数据
//3.1 插入位置为第一个
if(position == 0) {
// 修改头部指针
newNode.next = this.head;
this.head = newNode;
//3.2 插入中间位置
} else {
var index = 0;
var current = this.head;
var previous = null;
// 查找对应位置节点
while(index++ < position) {
previous = current;
current = current.next;
}
// 插入节点,修改指向
newNode.next = current;
previous.next = newNode;
}
//4.增加长度
this.length += 1;
return true;
}
4.查找某个位置(position)的值
LinkedList.prototype.getPosition = function(position) {
//1.越界判断
if(position < 0 || position >= this.length) return null;
//2.获得元素
// 指针
var current = this.head;
var index = 0;
while(index < position) {
current = current.next;
index++;
}
return current.data;
}
5.修改指定位置(position)数据
LinkedList.prototype.update = function(position, newData) {
//1.越界判断
if(position < 0 || position >= this.length) return null;
//2.获得元素
var current = this.head;
var index = 0;
while(index < position) {
current = current.next;
index++;
}
current.data = newData;
return true;
}
6.查找某个值的索引位置
LinkedList.prototype.indexOf = function(data) {
//1.定义变量
var current = this.head;
var index = 0;
//2.开始查找
while(current) {
// 找到节点,返回索引
if(current.data == data) {
return index;
}
// 下一个节点
current = current.next;
index++;
}
//3.在链表中没有找到该元素,返回-1
return -1;
}
7.删除指定位置数据(position),返回数据
LinkedList.prototype.removeAt = function(position) {
//1.越界判断
if(position < 0 || position >= this.length) return null;
//2.判断是否删除第一个节点
var current = this.head;
if(position == 0) {
this.head = this.head.next;
} else {
var index = 0;
var previous = null;
while (index++ < position) {
previous = current;
current = current.next;
}
//前一个节点的next指向current的next即可
previous.next = current.next;
}
// 3.长度减一
this.length -= 1;
return current.data;
}
8.删除某个值对应的节点
LinkedList.prototype.remove = function(data) {
//1.找到data在链表中的位置
var position = this.indexOf(data);
//2.根据位置信息,删除节点
return this.removeAt(position);
}
9.判断链表是否为空
LinkedList.prototype.isEmpty = function() {
return this.length == 0;
}
10.返回链表长度
LinkedList.prototype.size = function() {
return this.length;
}
js中单链表与数组对比
(1)查找对应数据value
乱序数组遍历找到对应数据,复杂度O(n)
排序数组折半查找找到对应数据,复杂度O(log2n)
链表遍历查找对应数据,复杂度O(n)
(2)按索引查找
数组复杂度O(1),链表O(n)
(3)插入、删除数据
尾部插入、删除:数组复杂度O(1),链表O(n)
任意位置插入、删除:数组需要平均移动半个表长的数据,链表只需要修改前后指针即可
(4)灵活性
链表在需要时可以申请新空间,操作灵活、高效
这是在b站上看coderwhy老师的课程整理的笔记,老师的官方博客:数据结构(五)之链表结构