Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中的LinkedList,如何将更改附加到列表中?_Javascript_Linked List - Fatal编程技术网

JavaScript中的LinkedList,如何将更改附加到列表中?

JavaScript中的LinkedList,如何将更改附加到列表中?,javascript,linked-list,Javascript,Linked List,我遇到了JavaScript中变量的引用问题,我一直在努力解决这个问题 我正在准备教授一门关于数据结构的课程,在至少10年没有看过材料之后,我正在复习这些材料 我在理论上知道链表,但出于某种原因,我很难想出能在JavaScript中实际工作的代码(我选择JavaScript是因为我的类最了解JavaScript) 这是我的代码: let LinkedList = { head: {}, tail: {} }; let Node = { data: {}, ne

我遇到了JavaScript中变量的引用问题,我一直在努力解决这个问题

我正在准备教授一门关于数据结构的课程,在至少10年没有看过材料之后,我正在复习这些材料

我在理论上知道链表,但出于某种原因,我很难想出能在JavaScript中实际工作的代码(我选择JavaScript是因为我的类最了解JavaScript)

这是我的代码:

let LinkedList  = {
    head: {},
    tail: {}
};

let Node = {
    data: {},
    next: {}
}

function isObjectEmpty(obj1) {
    return Object.keys(obj1).length === 0 && obj1.constructor === Object;
}

function count(node, counter) {
    if (node.next) {
        return 1 + count(node.next, counter);
    }
    return counter;
}

/**
 * Adds data to LinkedList
 * @param {LinkedList} list
 * @param {Node} data
 */
function add_node(list, data) {
    let temp = Object.assign({}, Node);
    temp.data = data;
    temp.next = {};

    if (Object.keys(list.head).length === 0) {
        list.head = temp;
        list.tail = temp;
    } else {
        list.tail.next = temp;
        list.tail = temp;
    }
    return list;
}
function insert(l, n, position) {
    if (position <= 0) {
        position = 0;
    } else {
        position = position - 1;
    }

    var list = Object.assign({}, l);
    var node = Object.assign({}, Node);
    node.data = n;

    // this only counts elements on the list.
    var elements = count(list.head, 0);

    if (position > elements) {
        return list;
    }

    var currentPosition = list.head;
    var counter = 0;

    while (!isObjectEmpty(currentPosition)) {
        if (position === counter) {
            var tmp = currentPosition;
            currentPosition = node;
            currentPosition.next = tmp.next;
            return list;
        }
        currentPosition = currentPosition.next;
        counter++;
    }

    return list;
}

// how to use the function
let songs = [
{id: '1', name: 'Kamikaze', artist: 'Eminem', releaseDate: '2018-08-31'},
{id: '2', name: 'despacito', artist: 'Luis Fonsi', releaseDate: '2018-08-31'},
{id: '3', name: 'La tortura', artist: 'Shakira', releaseDate: '2018-08-31'},
{id: '4', name: 'Roar', artist: 'Roar', releaseDate: '2018-08-31'},
 ];

let list = Object.assign({}, LinkedList);
    songs.forEach((song) => {
        add_node(list, song); // nothing special, just builds the linkedlist
     });

list = insert(list, {id: '5', name: 'Havana', artist:'who knows', releaseDate:'2018-01-01'}, 3); 
console.log(list); // new object isn't there.
您可以看到,我实际上正在成功地将新节点插入到我想要插入的位置

但是如果您
console.log
查看
list
结构,您将发现新插入的节点不存在

我不知道我在哪里失败了,也不知道为什么列表保留了旧的引用,而没有遵循新的“路径”


非常感谢任何指向正确方向的指针。

两个问题。首先,您要替换节点,而不是严格地插入。我想您希望
.next
成为
tmp
节点,而不是
tmp.next

currentPosition.next = tmp;
其次,需要在插入点之前保留对节点的引用,以便可以将其
next
值设置为新插入的节点:

previousNode.next = node //<- node being the one you're inserting

为了确保插入初始位置的安全性,我们必须能够设置
list.head
。否则,我们将设置上一个节点的
next
属性。

您可以使用没有
对象的版本。分配
并将对象作为列表和由相同命名函数创建的节点使用。这个函数可以在以后用实例化函数替换,以实现更OOP风格的方法

此方案将获取一个节点,并根据功能将其插入列表末尾或列表中的任何位置。如果列表中不存在节点,则会将其插入到链接列表的开头

函数链接列表(){
返回{head:null,tail:null};
}
功能节点(数据,下一步){
返回{data,next};
}
函数insertTail(列表,节点){
如果(列表标题){
list.tail.next=节点;
list.tail=list.tail.next;
}否则{
list.head=节点;
list.tail=节点;
}
退货清单;
}
函数insertPos(列表,节点,n){
var temp=列表头,
以前的
如果(!temp){
返回insertTail(列表、节点);
}
while(temp.next&&n--){
先前=温度;
温度=下一个温度;
}
node.next=temp;
previous.next=节点;
退货清单;
}
var songs=[{id:'1',名称:'Kamikaze',艺术家:'Eminem',发行日期:'2018-08-31'},{id:'2',名称:'despacito',艺术家:'Luis Fonsi',发行日期:'2018-08-31'},{id:'3',名称:'La tortura艺术家:'Shakira',发行日期:'2018-08-31'},{id:'4',名称:'Roar',艺术家:'Roar',发行日期:'2018-08-31'},
list=linkedList();
forEach(song=>insertTail(列表,节点(song));
控制台日志(列表);
insertPos(列表,节点({id:'5',名称:'Havana',艺术家:'who knows',发布日期:'2018-01-01'}),3);
控制台日志(列表)
。作为控制台包装{最大高度:100%!重要;顶部:0;}
如果在此块中放置调试器:

    if (position === counter) {
        var tmp = currentPosition;
        currentPosition = node;
        currentPosition.next = tmp.next;
        return list;
    }
if (position === counter) {
    var tmp = currentPosition;
    currentPosition = node;
    currentPosition.next = tmp.next;
    return list;
}
您可以看到,我实际上成功地插入了新节点 我想去哪里

不,你没有。如果我们删除
tmp
currentPosition
赋值混淆,则该位代码相当于

if (position === counter) {
    node.next = currentPosition.next;
    return list;
}
所发生的一切是,您正在将列表的尾部复制到新节点上,但您从未真正将该节点作为列表中当前节点的下一个插入。少了一个

currentPosition.next = node;

还有几点:

  • 不要使用
    isObjectEmpty
    和空对象来表示“无节点”。改用
    null
    。如果出于某种说教性原因,您不想引入
    null
    ,请在对象上使用布尔
    .isNode
    属性来区分包含数据的节点和空节点
  • 避免
    对象。分配
    。你的用法真的很不规范。在

    let temp = Object.assign({}, Node);
    temp.data = data;
    temp.next = {};
    
    您正在直接覆盖刚从
    节点复制的值
    -最好简化为使用对象文字:

    let temp = {data, next: {}};
    
    var list=Object.assign({},l)您根本不想创建新对象。您将对传入列表进行变异,因此您应该保留该列表。(如果要使纯函数具有不可变的数据结构,则必须使所有节点也不可变,并将克隆插入整个列表直到所需位置)

  • 如果
    Object.assign
    的目的是创建新对象,这些对象以后可能会涉及您不打算覆盖的其他属性(或方法),请改用factory函数

  • 不要事先清点清单。一次完成插入,如果您到达列表末尾,位置变为惰性,则返回

函数makeLinkedList(){
返回{head:null,tail:null};
}
函数makeNode(数据,下一步=null){
返回{data,next};
}
函数追加(列表、节点){
如果(列表标题){
list.tail.next=节点;
}否则{
list.head=节点;
}
list.tail=节点;
}
函数插入(列表、数据、位置){
如果(位置<0)抛出新错误(“位置必须为非负”);
设newNode=makeNode(数据);
让prev=null,cur=list.head;
while(cur!=null&&position>0){
prev=cur;
cur=cur.next;
位置--;
}

如果(cur==null&&position>0)抛出新错误(“position必须是那些
对象。assign
调用是伪造的,它不会克隆嵌套的对象。你能不能也添加一个例子,说明你将如何调用函数?什么是
esObjetoVacio
?你不应该在那里检查
null
吗?@Bergi I
let temp = {data, next: {}};
function makeLinkedList() {
    return { head: null, tail: null };
}

function makeNode(data, next = null) {
    return { data, next };
}

function append(list, node) {
    if (list.head) {
        list.tail.next = node;
    } else {
        list.head = node;
    }
    list.tail = node;
}

function insert(list, data, position) {
    if (position < 0) throw new Error("position must be nonnegative");

    let newNode = makeNode(data);
    let prev = null, cur = list.head;
    while (cur != null && position > 0) {
        prev = cur;
        cur = cur.next;
        position--;
    }
    if (cur == null && position > 0) throw new Error("position must be <= list length")
    if (cur == null) {
        list.tail = newNode;
    } else {
        newNode.next = cur;
    }
    if (prev == null) {
        list.head = newNode;
    } else {
        prev.next = newNode;
    }
}