单向链表 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始;链表是使用指针进行构造的列表;又称为结点列表,因为链表是由一个个结点组装起来的;其中每个结点都有指针成员变量指向列表中的下一个结点。
优点 :
(1)单个结点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的大小
(2)结点的删除非常方便,不需要像线性结构那样移动剩下的数据
(3)结点的访问方便,可以通过循环或者递归的方法访问到任意数据,但是平均的访问效率低于线性表
常用方法:
- append(data) 追加元素
- insert(position, data) 插入节点
- get(position) 查看元素
- indexOf(element) 返回元素在列表中的索引
- updata(position) 修改某个位置的元素
- remove(position/data) 从列表的特定位置(数据)移除一项
- isEmpty() 如果链表中不包含任何元素,返回true,否则为false
- size() 返回链表包含的元素个数,与数组的length类似
function Linkedlist() {
// 创建节点
function Node (data) {
this.data = data;
this.next = null
}
// 链表长度
this.length = 0;
// 初始化头指针
this.head = null
// 内封方法
// 1 append追加
Linkedlist.prototype.append = function (data) {
var newNode = new Node(data);
// 判断是否空链表
if (this.length === 0 ) {
this.head = newNode
}else{
let current = this.head
while (current.next){
current = current.next
}
// next指向新节点
current.next = newNode
}
// 更新链表长度
this.length += 1
}
// 2 toString转字符串
Linkedlist.prototype.toString = function () {
// 初始化当前节点
let current = this.head ;
// 转化结果
let result = ''
while (current) {
result += current.data;
current = current.next
}
return result
}
// 3 insert插入节点
Linkedlist.prototype.insert = function (position, data) {
// 1 对position进行越界判断
if (position < 0 || position >= this.length) return false
// 2 根据data创建节点
let newNode = new Node(data)
// 3 判断插入节点的位置,第一个头指针较为特殊
if (position === 0 ) {
newNode.next = this.head;
this.head = newNode;
}else{
let index = 0;
let current = this.head;
let preview = null;
while (index++ < position) {
preview = current;
current = current.next
}
// 前一个节点指向
preview.next = newNode;
// 新节点指向
newNode.next = current
}
this.length += 1;
}
// 4 get方法
Linkedlist.prototype.get = function (position) {
// 1 对position进行越界判断
if (position < 0 || position > this.length) return false
let index = 0;
let current = this.head;
while (index++ < position) {
current = current.next
}
return current.data
}
// 5 indexOf(element)返回元素在列表中的索引
Linkedlist.prototype.indexOf = function (element) {
let current = this.head;
let index = 0;
while (current) {
if (current.data === element) {
return index
}
current = current.next;
index += 1;
}
return false
}
// 6 updata(position)修改某个位置的元素
Linkedlist.prototype.updata = function (position, newdata) {
// 由于又position信息,故需要进行越界判断
if (position < 0 || position >= this.length) return false
let current = this.head;
let index = 0;
while (index++ < position) {
current = current.next;
}
current.data = newdata;
}
// 7 remove(position)从列表的特定位置移除一项
Linkedlist.prototype.removeAt = function (position) {
if (position < 0 || position >= this.length) return null
let current = this.head;
// 当头指针需要剔除时
if (position === 0 ) {
this.head = this.head.next
}
var index = 0;
while (index++ < position-1) {
current = current.next;
}
current.next = current.next.next
}
// 8 remove(element)从列表中移除一项
Linkedlist.prototype.remove = function (element) {
// 查找位置
let position = this.indexOf(element);
// 删除
return this.removeAt(position);
}
// 9 isEmpty() 如果链表中不包含任何元素,返回true,否则为false
Linkedlist.prototype.isEmpty = function () {
return this.length === 0
}
// 10 size() 返回链表包含的元素个数,与数组的length类似
Linkedlist.prototype.size = function () {
return this.length
}
}
// 测试用例
let A = new Linkedlist();
A.append('111')
A.append('222')
A.append('333')
console.log(A);
console.log(A.toString());
// 测试insert
A.insert(1, 'aaa');
console.log(A.toString());
// 测试get 方法
console.log(A.get(2));
// 测试indexOf
console.log(A.indexOf('333'));
// 测试updata
A.updata(0, 'updata');
console.log(A.toString());
// 测试removeAt
// A.removeAt(2);
// console.log(A.toString());
// 测试remove
A.remove('333');
console.log(A.toString());