相关概念
1.如果你发现数组在实际使用时很慢,就可以考虑使用链表来替代它。
因为,JavaScript 中数组的主要问题是,它们被实现成了对象,与其他语言(比如 C++ 和 Java)的数组相比,效率很低
2.链表是由一组节点组成的集合。
3.每个节点都使用一个对象的引用指向它的后继。
4.指向另一个节点的引用叫做链。
5.数组元素靠它们的位置进行引用,链表元素则是靠相互之间的关系进行引用。
代码
// 1.基础链表
// Node类表示节点
// LinkedList类提供了插入节点、删除节点、显示列表元素的方法,辅助方法
// Node类
function Node(element) {
this.element = element
this.next = null
}
// LinkedList类
function LList() {
this.head = new Node('head')
this.find = find
this.insert = insert
this.findPrevious = findPrevious
this.remove = remove
this.display = display
}
// 找到一个节点--find()
function find(item) {
var currNode = this.head
while (currNode.element != item) {
currNode = currNode.next
}
return currNode
}
// 插入新节点--insert()
function insert(newElement, item) {
var newNode = new Node(newElement)
var current = this.find(item)
newNode.next = current.next
current.next = newNode
}
// 显示链表元素
function display() {
var currNode = this.head
while (!(currNode.next == null)) {
console.log(currNode.next.element)
currNode = currNode.next
}
}
// var cities = new LList()
// cities.insert("Conway", "head");
// cities.insert("Russellville", "Conway");
// cities.insert("Alma", "Russellville");
// cities.display()
// 找到前一个元素
function findPrevious(item) {
var currNode = this.head
while (!(currNode.next == null) && (currNode.next.element != item)) {
currNode = currNode.next
}
return currNode
}
// remove()
function remove(item) {
var prevNode = this.findPrevious(item)
if (!(prevNode.next == null)) {
prevNode.next = prevNode.next.next
}
}
// 测试
var cities = new LList();
cities.insert("Conway", "head");
cities.insert("Russellville", "Conway");
cities.insert("Carlisle", "Russellville");
cities.insert("Alma", "Carlisle");
cities.display();
cities.remove("Carlisle");
cities.display();
// 链表的其他方法
// 在链表中向前移动n个节点
// advance(n)
// 在双向链表中向后移动n个节点
// back(n)
// 只显示当前节点
// show()
// 2.循环链表
// Node类
function Node(element) {
this.element = element
this.next = null
}
// LinkedList类
function LList() {
this.head = new Node('head')
this.head.next = this.head
this.find = find
this.insert = insert
this.display = display
this.findPrevious = findPrevious
this.remove = remove
}
// 找到一个节点--find()
function find(item) {
var currNode = this.head
while ((currNode.element != item) && !(currNode.next.element == 'head')) {
currNode = currNode.next
}
return currNode
}
// 插入新节点--insert()
function insert(newElement, item) {
var newNode = new Node(newElement)
var current = this.find(item)
newNode.next = current.next
current.next = newNode
}
// 显示链表元素
function display() {
var currNode = this.head
while (!(currNode.next == null) && !(currNode.next.element == 'head')) {
console.log(currNode.next.element)
currNode = currNode.next
}
}
// 测试代码一
var cities = new LList()
cities.insert("Conway", "head");
cities.insert("Russellville", "Conway");
cities.insert("Alma", "Russellville");
cities.display()
// 找到前一个元素
function findPrevious(item) {
var currNode = this.head
while (!(currNode.next == null) && (currNode.next.element != item)) {
currNode = currNode.next
}
return currNode
}
// remove()
function remove(item) {
var prevNode = this.findPrevious(item)
if (!(prevNode.next == null)) {
prevNode.next = prevNode.next.next
}
}
// 测试代码二
var cities = new LList();
cities.insert("Conway", "head");
cities.insert("Russellville", "Conway");
cities.insert("Carlisle", "Russellville");
cities.insert("Alma", "Carlisle");
cities.display();
cities.remove("Carlisle");
cities.display();
// 2.双向链表
// Node类
function Node(element) {
this.element = element
this.next = null
this.previous = null
}
// LinkedList类
function LList() {
this.head = new Node('head')
this.find = find
this.insert = insert
this.display = display
this.remove = remove
this.findLast = findLast
this.dispReverse = dispReverse
}
// 找到一个节点--find()
function find(item) {
var currNode = this.head
while (currNode.element != item) {
currNode = currNode.next
}
return currNode
}
// 插入新节点--insert()
function insert(newElement, item) {
var newNode = new Node(newElement)
var current = this.find(item)
newNode.next = current.next
newNode.previous = current
current.next = newNode
}
// 显示链表元素
function display() {
var currNode = this.head
while (!(currNode.next == null)) {
console.log(currNode.next.element)
currNode = currNode.next
}
}
// 测试代码一
var cities = new LList()
cities.insert("Conway", "head");
cities.insert("Russellville", "Conway");
cities.insert("Alma", "Russellville");
cities.display()
// remove()
function remove(item) {
var currNode = this.find(item)
if (!(currNode.next == null)) {
currNode.previous.next = currNode.next
currNode.next.previous = currNode.previous
currNode.next = null
currNode.previous = null
}
}
// findLast()
function findLast() {
var currNode = this.head
while (!(currNode.next == null)) {
currNode = currNode.next
}
return currNode
}
// 反序显示双向链表中的元素
function dispReverse() {
var currNode = this.head
currNode = this.findLast()
while (!(currNode.previous == null)) {
console.log(currNode.element)
currNode = currNode.previous
}
}
// 测试代码二
var cities = new LList()
cities.insert("Conway", "head")
cities.insert("Russellville", "Conway")
cities.insert("Carlisle", "Russellville")
cities.insert("Alma", "Carlisle")
cities.display()
console.log('------------')
cities.remove("Carlisle")
cities.display()
console.log('------------')
cities.dispReverse()
力扣相关题目
以下题目难度全部为简单:
1.1.题目描述:
- 删除链表中的节点
请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
现有一个链表 – head = [4,5,1,9],它可以表示为: 4 —> 5 —> 1 —> 9
1.2.示例:
输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
输入: head = [4,5,1,9], node = 1
输出: [4,5,9]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-node-in-a-linked-list
1.3.我的解答:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val = node.next.val
node.next = node.next.next
};
2.1.题目描述:
- 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
2.2.示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-node-in-a-linked-list
2.3.我的解答:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var mergeTwoLists = function(l1, l2) {
// 执行用时: 128 ms, 在所有 JavaScript 提交中击败了13.19%的用户
// 内存消耗 :38.9 MB, 在所有 JavaScript 提交中击败了100.00%的用户
var arr1 = []
var arr2 = []
// 链表转数组
function listToArray (head) {
var item = head
var arr = []
while(!(item == null)){
arr.push(item.val)
item = item.next
}
return arr
}
arr1 = listToArray(l1)
arr2 = listToArray(l2)
// 数组转链表
function arrayToList (arr) {
if (arr.length === 0) {
return null
}
var arrs = []
for(var i=0; i<arr.length; i++){
arrs.push(new ListNode(arr[i]))
}
for(var i=0; i<arrs.length-1; i++){
arrs[i].next = arrs[i+1]
}
return arrs[0]
}
var arr = []
if (arr1.length && arr2.length) {
arr = ([].concat(arr1, arr2)).sort(function(a,b){return (a-b)})
} else if (arr1.length && !arr2.length) {
arr = arr1.sort(function(a,b){return (a-b)})
} else if (!arr1.length && arr2.length) {
arr = arr2.sort(function(a,b){return (a-b)})
} else {
arr = []
}
return (arrayToList(arr))
};
3.1.题目描述:
- 二进制链表转整数
给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。
请你返回该链表所表示数字的 十进制值 。
3.2.示例:
输入:head = [1,0,1]
输出:5
输入:head = [0]
输出:0
输入:head = [1]
输出:1
输入:head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0]
输出:18880
输入:head = [0,0]
输出:0
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/convert-binary-number-in-a-linked-list-to-integer
3.3.我的解答:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {number}
*/
var getDecimalValue = function(head) {
if(!head.next){
return head.val
}
var arr = []
var obj = {}
do{
arr.push(head.val)
head = head.next
}while(head.next !== null)
arr.push(head.val)
var add = 0
for(var i=0; i<arr.length; i++){
if(arr[arr.length-1-i] === 1){
add += Math.pow(2,i)
}
}
return add
};
4.1.题目描述:
面试题24. 反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
4.2.示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-node-in-a-linked-list
4.3.我的解答:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
// console.log(head)
var arr = []
var item = head
function ListNode(val) {
this.val = val;
this.next = null;
}
while(item !== null){
arr.push(item.val)
item = item.next
}
arr = arr.reverse()
// console.log('arr', arr)
function list(ary) {
if(ary.length === 0) {
return null
}
var nodes = []
for(var i = 0; i < ary.length; i++) {
var node = new ListNode(ary[i])
nodes.push(node)
}
for(var i = 0; i < nodes.length - 1; i++) {
nodes[i].next = nodes[i + 1]
}
return nodes[0]
}
ListNode = list(arr)
// console.log(ListNode)
return ListNode
};
5.1.题目描述:
面试题18. 删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
5.2.示例:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof
5.3.我的解答:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var deleteNode = function(head, val) {
var item = head
// 找到前一个节点
// var currNode = head
// while(!(currNode.next == null) && (currNode.next.val != val)) {
// currNode = currNode.next
// }
// var prevNode = currNode
// if (!(prevNode.next == null)) {
// prevNode.next = prevNode.next.next
// }
// 如果链表只有一层
if (head.next == null){
return null
}
while(!(item.next == null)){
// 如果链表超过一层并且删除链表头元素
if (item.val == val) {
head = item.next
}
if (item.next.val === val) {
item.next = item.next.next
} else {
item = item.next
}
}
return head
};
本文深入解析链表的基本概念、实现与操作,包括单链表、循环链表及双向链表,并通过LeetCode实战题目如删除节点、合并有序链表等,提升链表编程技能。

被折叠的 条评论
为什么被折叠?



