mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-06-16 21:06:35 +08:00
feat(curriculum): add Linked list lab (#56046)
Co-authored-by: Zaira <33151350+zairahira@users.noreply.github.com>
This commit is contained in:
parent
df08bef374
commit
295f537c99
@ -2127,7 +2127,12 @@
|
||||
"nixz": { "title": "262", "intro": [] },
|
||||
"zywg": { "title": "263", "intro": [] },
|
||||
"wraf": { "title": "264", "intro": [] },
|
||||
"kwxs": { "title": "265", "intro": [] },
|
||||
"lab-linked-list-class": {
|
||||
"title": "Build a Linked List Class",
|
||||
"intro": [
|
||||
"For this lab, you will build a linked list class using JavaScript."
|
||||
]
|
||||
},
|
||||
"muyw": { "title": "266", "intro": [] },
|
||||
"mvzb": { "title": "267", "intro": [] },
|
||||
"rmpy": { "title": "268", "intro": [] },
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Build a Linked List Class
|
||||
block: lab-linked-list-class
|
||||
superBlock: front-end-development
|
||||
---
|
||||
|
||||
## Introduction to the Build a Linked List Class
|
||||
|
||||
For this lab, you will build a linked list class using JavaScript.
|
||||
11
curriculum/challenges/_meta/lab-linked-list-class/meta.json
Normal file
11
curriculum/challenges/_meta/lab-linked-list-class/meta.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "Build a Linked List Class",
|
||||
"isUpcomingChange": true,
|
||||
"usesMultifileEditor": true,
|
||||
"blockType": "lab",
|
||||
"dashedName": "lab-linked-list-class",
|
||||
"order": 265,
|
||||
"superBlock": "front-end-development",
|
||||
"challengeOrder": [{ "id": "66dadcf18df3a76104054d95", "title": "Build a Linked List Class" }],
|
||||
"helpCategory": "JavaScript"
|
||||
}
|
||||
@ -0,0 +1,267 @@
|
||||
---
|
||||
id: 66dadcf18df3a76104054d95
|
||||
title: Build a Linked List Class
|
||||
challengeType: 14
|
||||
dashedName: build-a-linked-list-class
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In this lab, you'll build a linked list, which is a linear collection of data elements, called <dfn>nodes</dfn>, where each node points to the next node in the linked list. Each node in a linked list contains two key pieces of information: the element itself, and a reference to the next node.
|
||||
|
||||
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
|
||||
|
||||
**User Stories:**
|
||||
|
||||
1. You should create a class named `LinkedList` to represent a linked list data structure.
|
||||
|
||||
1. Each time a new `LinkedList` object is instantiated, its `length` and `head` properties should be set to `0` and `null`, respectively.
|
||||
|
||||
1. The `LinkedList` class should have a property `Node`, which is a class instantiated with an `element` property set to the value passed at the instantiation, and a `next` property set to `null`.
|
||||
|
||||
1. The `LinkedList` class should have a method `isEmpty` that returns `true` if the linked list is empty, and `false` otherwise.
|
||||
|
||||
1. The `LinkedList` class should have a method `add` that creates a `Node` object from its argument and adds it to the linked list.
|
||||
|
||||
1. The `add` method should either set the head to the new node when the node to be added is the first, or set the `next` property of the last node in the linked list to the node to be added.
|
||||
|
||||
1. Each time a new node is added to the list the length of the list should be incremented.
|
||||
|
||||
1. The `LinkedList` class should have a method `remove` that takes a single argument and removes the corresponding node from the list.
|
||||
|
||||
1. Whenever a node is removed from the linked list, the `next` property of the previous node should be set to the following node, and the length of the list should be decremented.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your `LinkedList` class should instantiate objects with the `length` property set to `0`.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
assert.strictEqual(test.length, 0);
|
||||
```
|
||||
|
||||
Your `LinkedList` class should instantiate objects with the `head` property set to `null`.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
assert.strictEqual(test.head, null);
|
||||
```
|
||||
|
||||
Your `LinkedList` class should have a property `Node`.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
assert.property(test, "Node");
|
||||
```
|
||||
|
||||
Your `Node` property should be a class that instantiates objects with an `element` property set to the value passed at the instantiation.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
const node = new test.Node("pig");
|
||||
assert.strictEqual(node.element, "pig");
|
||||
```
|
||||
|
||||
Your `Node` property should be a class that instantiates objects with a `next` property set to `null`.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
const node = new test.Node("pig");
|
||||
assert.strictEqual(node.next, null);
|
||||
```
|
||||
|
||||
Your `LinkedList` class should have an `add` method.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
assert.typeOf(test.add, 'function');
|
||||
```
|
||||
|
||||
Your `add` method should assign `head` to the first node object added to the linked list.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
const expected = { element: "pig", next: null }
|
||||
assert.deepEqual(test.head, expected);
|
||||
```
|
||||
|
||||
Your `add` method should set the `next` property of the last node in the linked list to the node to be added.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
test.add("dog")
|
||||
const expected = { element: "pig", next: {element: "dog", next: null} }
|
||||
assert.deepEqual(test.head, expected);
|
||||
```
|
||||
|
||||
Each time a new node is added to the list the `length` of the list should be incremented.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
assert.strictEqual(test.length, 1);
|
||||
test.add("dog");
|
||||
assert.strictEqual(test.length, 2);
|
||||
test.add("sheep");
|
||||
assert.strictEqual(test.length, 3);
|
||||
```
|
||||
|
||||
Your `LinkedList` class should have an `isEmpty` method.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
assert.typeOf(test.isEmpty, 'function');
|
||||
```
|
||||
|
||||
Your `isEmpty` method should return `false` when there is at least one element in the linked list.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add('pig');
|
||||
test.add('dog');
|
||||
test.add('kitten');
|
||||
assert.isFalse(test.isEmpty());
|
||||
```
|
||||
|
||||
Your `isEmpty` method should return `true` when there are no elements in linked list.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
assert.isTrue(test.isEmpty());
|
||||
```
|
||||
|
||||
The previous node in your `LinkedList` class should have a reference to the newest node created.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
test.add("dog")
|
||||
test.add("sheep");
|
||||
assert(test.head.next.element === 'dog' && test.head.next.next.element === "sheep");
|
||||
```
|
||||
|
||||
Your `LinkedList` class should have a `remove` method.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
assert.typeOf(test.remove, 'function');
|
||||
```
|
||||
|
||||
Your `remove` method should reassign `head` to the second node when the first node is removed.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
test.add("dog");
|
||||
test.add("sheep");
|
||||
test.remove("pig");
|
||||
const expected = { element: "dog", next: {element: "sheep", next: null} }
|
||||
assert.deepEqual(test.head, expected);
|
||||
```
|
||||
|
||||
Your `remove` method should decrease the `length` of the linked list by one for every node removed.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
test.add("dog");
|
||||
test.add("sheep");
|
||||
test.remove("pig");
|
||||
assert.strictEqual(test.length, 2);
|
||||
test.remove("dog");
|
||||
assert.strictEqual(test.length, 1);
|
||||
test.remove("sheep");
|
||||
assert.strictEqual(test.length, 0);
|
||||
```
|
||||
|
||||
Your `remove` method should reassign the reference of the previous node of the removed node to the removed node's `next` reference.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
test.add("dog");
|
||||
test.add("sheep");
|
||||
test.add("cat");
|
||||
test.remove("sheep");
|
||||
const expected = { element: "pig", next: {element: "dog", next: {element: "cat", next: null}} }
|
||||
assert.deepEqual(test.head, expected);
|
||||
```
|
||||
|
||||
Your `remove` method should not change the linked list if the element does not exist in the linked list.
|
||||
|
||||
```js
|
||||
const test = new LinkedList();
|
||||
test.add("pig");
|
||||
test.add("dog");
|
||||
test.add("sheep");
|
||||
test.add("cat");
|
||||
test.remove("elephant");
|
||||
const expected = { element: "pig", next: {element: "dog", next: {element: "sheep", next: {element: "cat", next: null}}} }
|
||||
assert.deepEqual(test.head, expected);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```js
|
||||
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
class LinkedList {
|
||||
constructor() {
|
||||
this.length = 0;
|
||||
this.head = null;
|
||||
}
|
||||
|
||||
Node = class {
|
||||
constructor(element) {
|
||||
this.element = element;
|
||||
this.next = null;
|
||||
}
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return this.length === 0;
|
||||
}
|
||||
|
||||
add(element) {
|
||||
const node = new this.Node(element)
|
||||
if (this.isEmpty()) {
|
||||
this.head = node;
|
||||
} else {
|
||||
let currentNode = this.head;
|
||||
while (currentNode.next !== null) {
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
currentNode.next = node;
|
||||
}
|
||||
this.length++;
|
||||
}
|
||||
|
||||
remove(element) {
|
||||
if (this.isEmpty()) {
|
||||
return
|
||||
}
|
||||
let previousNode;
|
||||
let currentNode = this.head;
|
||||
while (currentNode.next !== null && currentNode.element !== element) {
|
||||
previousNode = currentNode;
|
||||
currentNode = currentNode.next;
|
||||
}
|
||||
if (currentNode.next === null && currentNode.element !== element) {
|
||||
return;
|
||||
} else if (previousNode) {
|
||||
previousNode.next = currentNode.next
|
||||
} else {
|
||||
this.head = currentNode.next;
|
||||
}
|
||||
this.length--
|
||||
}
|
||||
}
|
||||
```
|
||||
Loading…
Reference in New Issue
Block a user