《数据结构与算法JavaScript描述》链表(学习笔记C06)

相关概念

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.题目描述:

  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.题目描述:

  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.题目描述:

  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
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值