【问题标题】:Unable to convert class syntax to function syntax for a Linked List无法将类语法转换为链表的函数语法
【发布时间】:2022-01-08 15:56:47
【问题描述】:

好的,我正在学习数据结构,我的教程遵循class 语法。所以现在我正试图将其转换为 function 声明,因为我想使用该符号练习链接列表。有人可以帮我转换吗?我只需要转换一种方法,其余的我就可以完成。

这是我使用class 语法的代码:

class Node {
    constructor( val ) {
        this.val = val;
        this.next = null;
    }
}

class SinglyLinkedList {
    constructor () {
        this.head = null;
        this.tail = null;
        this.length = 0;
    }

    push( val ) {
        const newNode = new Node( val );

        if ( !this.head ) {
            this.head = newNode;
            this.tail = this.head;
        } else {
            this.tail.next = newNode;
            this.tail = newNode;
        }
        this.length++
        return this;
    }

}

const list = new SinglyLinkedList();

list.push( 'HELLO' );
list.push( 'WORLD' );

这是我迄今为止尝试实现基于函数的方法:

function Node( val ) {
  this.val = val;
  this.next = null;
}

let head = null;
let tail = null;
let length = 0;

const SinglyLinkedListFunc = function() {
    const newNode = new Node( 'HELLO' );
};

SinglyLinkedListFunc()

这是我目前所能达到的。我被它困住了,我不知道下一步该做什么。有人请帮忙

【问题讨论】:

  • 呃,链表(节点)是一个对象。您不能将其更改为局部变量。
  • 仅仅因为你使用了构造函数并不能使它起作用。任何。您需要两个构造函数。一个用于节点,一个用于列表。
  • 真正实用(因此:不可变)的方法会使push 效率低下,因为它需要复制整个列表。你为什么想要那个?
  • @s.khan “功能”并不意味着您不再使用对象或类。相反,你仍然应该让你的代码更有条理!但是,函数式方法意味着您不应再修改(变异)您的对象,而是创建作为操作(方法、函数)结果返回的新对象。
  • @ScottSauyet,当然,prepending 可以通过函数式方法有效地完成,但不是 appending,这是 Asker 用他们的push。无论如何,Asker 最终要求的不是函数式方法,而是不使用 class 语法的版本。

标签: javascript algorithm data-structures linked-list singly-linked-list


【解决方案1】:

链表是一种功能结构,因此将其与功能样式一起使用会产生最佳效果。这意味着避免诸如突变和变量重新分配之类的事情。下面我们在面向对象的接口中实现一个函数式的不可变链表——

class Node {
  constructor(head, tail) {
    this.head = head
    this.tail = tail
  }
}

const empty = Symbol("empty")
  
class List {
  constructor(t = empty) {
    this.t = t
  }
  push(v) {
    return new List(new Node(v, this.t))
  }
  toString() {
    if (this.t == empty)
      return "∅"
    else
      return `${this.t.head} -> ${new List(this.t.tail)}`
  }
}

const l = (new List).push("a").push("b").push("c")
console.log(String(l))
console.log(String(l.push("d").push("e").push("f")))
console.log(String(l))

注意每次对.push 的调用如何返回一个新的、未修改的列表 -

c -> b -> a -> ∅
f -> e -> d -> c -> b -> a -> ∅
c -> b -> a -> ∅

但我认为你可以做得比这更好。通过将功能设计和关注点与面向类的语义直接混合在一起,我们最终会得到奇怪且通常效率低下的程序。在函数式风格中,我们编写具有普通函数的模块。如果需要一个面向对象的接口,只需要对我们的普通函数进行一个薄包装 -

// list.js
const empty = Symbol("empty")

const pair = (left, right) =>
  ({ left, right })

const toString = t =>
  t == empty
    ? "∅"
    : `${t.left} -> ${toString(t.right)}`

const push = (t, v) =>
  pair(v, t)

class List {
  static of(t) { return new List(t) }
  constructor(t = empty) { this.t = t }
  push(v) { return List.of(push(this.t, v)) }
  toString() { return toString(this.t) }
}

const list = List.of

export default list

在您的 ma​​in 模块中,我们将从 list 模块中导入 list -

// main.js
import list from "./list.js"

const l = list().push("a").push("b").push("c")
console.log(String(l))
console.log(String(l.push("d").push("e").push("f")))
console.log(String(l))
c -> b -> a -> ∅
f -> e -> d -> c -> b -> a -> ∅
c -> b -> a -> ∅

展开下面的 sn-p 以在浏览器中验证结果 -

// list.js
const empty = Symbol("empty")

const pair = (left, right) =>
  ({ left, right })

const toString = t =>
  t == empty
    ? "∅"
    : `${t.left} -> ${toString(t.right)}`

const push = (t, v) =>
  pair(v, t)

class List {
  static of(t) { return new List(t) }
  constructor(t = empty) { this.t = t }
  push(v) { return List.of(push(this.t, v)) }
  toString() { return toString(this.t) }
}

const list = List.of

// main.js
const l = list().push("a").push("b").push("c")
console.log(String(l))
console.log(String(l.push("d").push("e").push("f")))
console.log(String(l))

【讨论】:

    【解决方案2】:

    这是函数式方法:

    function Node( val, next ) {
      this.val = val;
      this.next = null;
    }
     
    const SinglyLinkedListFunc = function() {
        this.head = null;
        this.tail = null;
        this.length = 0;
    };
    
    SinglyLinkedListFunc.prototype.push = function( val ) {
    
      const newNode = new Node( val );
    
      if( !this.head ){
        this.head = newNode;
        this.tail = newNode;
      } else{
        this.tail.next = newNode;
        this.tail = newNode;
      }
    
        this.length++;
        return this;
    }
    
    
    let list = new SinglyLinkedListFunc();
    list.push('HELLO');
    list.push('WORLD');
    

    【讨论】:

    • 这不是functionalpush 改变了违反函数式编程的列表。
    • 我在帖子中从未说过我想要函数式编程。我只是想使用函数而不是类。
    • 你也说过“用功能方法。”。这不仅仅是编写函数。
    • 我也是这么说的:所以现在我正在尝试将其转换为函数
    • @s.khan:即使函数式方法不是您想要的,也值得研究一下 Mulan 的答案,它展示了一种非常不同的代码查看方式。
    猜你喜欢
    • 2021-12-21
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    相关资源
    最近更新 更多