詩を考えます
伤情最是晚凉天,憔悴厮人不堪言;
邀酒摧肠三杯醉.寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘;
小楼寂寞新雨月.也难如钩也难圆。
序文
リストだけでなく、プロセスと、リストの原則の実現 - この章では、この章では、データ構造について主にある、記事の「JavaScriptのデータ構造とアルゴリズムの学習」シリーズを再読しました。
リスト
リスト、なぜこのようなデータ構造を持っていますか?もちろん、すべてが理由で起こりました!
最も一般的で便利なデータ構造、 -配列しかし、我々は要素を移動する必要があるため、我々は、高価な出発または中間配列からアイテムを挿入したり、移動し、。
リストは、順序付けられた要素の集合を格納しています。リストメモリ内の要素は連続して配置されていない、各要素自体は、記憶素子で構成され、ノードが参照(ポインタまたはリンク)は、組成物中の要素を指します。
これは、注意、リングアップの焦点である、インタビューをテストしてください!
リンクリストの実装
構造および対応する方法我々は、およそ、リストを達成するために、次のとおりです。より詳細にロジックを実装するコードを参照するには要素の挿入、削除、アクセスリストの長さは、クエリ要素が空である、など...。
もっと複雑なデータ構造を自分で...の精神を理解するために注意を払います...
/**
* Node 节点类,用于生成自身节点与下一个元素的引用
*/
class Node {
constructor(element) {
this.element = element
this.next = undefined
}
}
/**
* defaultEquals() 用于比较两个非对象类的值是否相等
*/
function defaultEquals (a, b) {
return a === b
}
/**
* LinkedList 链表
* 特点:链表存储有序的元素集合,但元素在内存中并不连续存放。每个元素有一个存储元素本身的节点和一个指向下一个元素的引用
*/
class LinkedList {
constructor (equalsFn = defaultEquals) {
// 链表长度
this.count = 0
// 第一个元素引用
this.head = undefined
// 用于比较元素是否相等,默认为defaultEquals,允许传入自定义的函数来比较两个对象是否相等。
this.equalsFn = equalsFn
}
}
注:オブジェクト土類元素を比較するときequalsFnパラメータは、2つの値が等しいオブジェクトで比較するカスタムメソッドを通過する必要があります。
押す()
リストの最後に要素を追加します。
/**
* push() 添加元素到链表
* @param {*} element 待添加的元素
*/
push (element) {
let node = new Node(element)
let current
// 判断链表是否为空
if (this.head == null) {
this.head = node
} else {
// 查询最后的元素 - 特点 current.next == null
current = this.head
while (current.next != null) {
current = current.next
}
// 将最后元素的下一个元素引用指向node
current.next = node
}
this.count++
}
getElementAt()
要素のインデックス位置を取得します。
/**
* getElementAt() 返回索引位置元素
* @param {Number} index 索引位置
* @returns {*} node
*/
getElementAt (index) {
// 判断索引是否有效
if (index < 0 || index > this.count) {
return undefined
}
let node = this.head
for (let i = 0; i < index && node != null; i++) {
node = node.next
}
return node
}
インサート()
インデックス位置にある任意の要素を挿入します
/**
* insert() 在任意位置插入元素
* @param {*} element 待插入的元素
* @param {Number} index 指定的索引位置
* @returns {Boolean}
*/
insert (element, index) {
// 判断是否为合法index
if (index < 0 || index > this.count) {
return false
}
// 实例化节点
let node = new Node(element)
// 插入-第一个位置
if (index === 0) {
let current = this.head
node.next = current
this.head = node
} else {
// 查找到指定索引位置的前一个元素
let previous = this.getElementAt(index - 1)
let current = previous.next
// 将上一个元素的next引用指向当前新添加的node,将node的next引用指向current,则完成插入
previous.next = node
node.next = current
}
// 链表长度+1
this.count++
return true
}
removeAt()
指定したインデックスにある要素を削除します
ロジックを実装する:それは最初のものである場合は、リストの最初の項目は、第2の要素はポイントをthis.headことができるかどうかを決定することと、最初のない、インデックスインデックスが前の要素の位置インデックス上の位置を取得した場合、及び次の位置のインデックス要素current.nextは、previous.nextはcurrent.nextを指すことができます
/**
* removeAt() 移除指定位置的元素
* @param {Number} index
* @returns {*} element 移除的元素
*/
removeAt (index) {
// 判断是否是合法索引
if (index < 0 || index > this.count) {
return undefined
}
let current = this.head
// 考虑是否是链表第一项
if (index === 0) {
this.head = current.next
} else {
// 方法一、 使用for循环迭代获取指定索引位置的元素
// 用于获取上一位置元素
// let previous
// for (let i = 0; i < index; i++) {
// previous = current
// current = current.next
// }
// // 跳过当前元素,将上一个元素的next指向下一个元素
// previous.next = current.next
// 方法二、借助getElementAt()方法
// 查询该索引位置的上一个元素
let previous = this.getElementAt(index - 1)
// 跳过中间元素,将上一个元素的next指向下一个元素
current = previous.next
previous.next = current.next
}
this.count--
return current.element
}
の指標()
要素のクエリのインデックス位置
ロジック実装;カスタムメソッドでオブジェクトクラスパスの値が等しいかどうかのために比較されることに留意することが重要で、繰り返し要素を各要素とターゲット要素を比較して等しいです
/**
* indexOf() 查询元素的索引位置
* @param {*} element 待查询的元素
* @returns {Number} index 索引位置,不存在则返回-1
*/
indexOf (element) {
let current = this.head
for (let i = 0; i < this.count && current != null; i++) {
// 判断两个元素是否相同
if (this.equalsFn(element, current.element)) {
return i
}
current = current.next
}
return - 1
}
削除()
指定された要素を削除します。
/**
* remove() 移除元素
* @param {*} element 待移除的元素
* @returns {*} element 移除的元素
*/
remove (element) {
// 获取索引位置
let index = this.indexOf(element)
// 移除指定索引位置的元素
return this.removeAt(index)
}
サイズ()
リストの長さを取得します。
/**
* size() 返回链表长度
* @returns {Number} 链表长度
*/
size () {
return this.count
}
isEmpty()
リストが空であるかどうかの判定
/**
* isEmpty() 判断链表是否为空
* @returns {Boolean}
*/
isEmpty () {
return this.count === 0
}
getHead()
リストの最初の要素を取得します。
/**
* getHead() 获取链表首位元素
* @returns {*}
*/
getHead () {
if (this.head != null) {
return this.head.element
}
return undefined
}
クリア()
空のリスト
/**
* clear() 清空链表
*/
clear () {
this.count = 0
this.head = undefined
}
toString()
文字列の処理リスト
/**
* toString() 链表字符串化展示
* @returns {String}
*/
toString () {
// 判断是否为空
if (this.isEmpty()) {
return ''
}
let objStr = `${this.head.element}`
let current = this.head.next
for (let i = 1; i < this.count; i++) {
objStr = `${objStr},${current.element}`
current = current.next
}
return objStr
}
リストを使用します
let linkedList = new LinkedList()
console.log(linkedList.isEmpty()) // true
// push 尾部压入元素
linkedList.push(15)
linkedList.push(20)
/*
LinkedList {
count: 2,
head: Node {
element: 15,
next: Node {
element: 20,
next: undefined
}
},
equalsFn: [Function: defaultEquals]
}
*/
console.log(linkedList)
console.log(linkedList.isEmpty()) // false
// getElementAt() 指定索引位置的元素
let node = linkedList.getElementAt(1)
console.log(node)
// insert() 任意索引位置插入元素
linkedList.insert(22, 1)
linkedList.insert(33, 1)
console.log(linkedList.toString()) // 15,33,22,20
// removeAt() 移除指定索引位置的元素
console.log(linkedList.removeAt(1)) // 33
// remove() 移除元素
console.log(linkedList.remove(15)) // 15
console.log(linkedList.toString()) // 22,20
console.log(linkedList.getHead()) // 22
console.log(linkedList.size()) // 2
console.log(linkedList.toString()) // 22,20
console.log(linkedList.isEmpty()) // false
linkedList.clear()
console.log(linkedList.isEmpty()) // true
再び下に:リストはオブジェクト型の値に格納されている場合は、自分自身を比較equalsFn指定された比較関数を渡すようにしてください、あなたはなぜ知っておくべき!
追伸
そして、胡兄弟、今日は小さなパートナーが覚えているように、コンテンツを共有すること收藏
、および转发
右下のボタンをクリックして在看
、それをお勧めするよりジュニアパートナーヨ、メッセージ交換の多くに歓迎...
胡弟の何かが、スキル、胡弟の気持ちを言うために!Jingdongはオープンプラットフォームのチーフフロントエンド包囲ライオン。あなたと話ビッグフロントエンド、フロントエンド共有システムアーキテクチャフレームワークの実装原則、最新かつ最も効率的な技術の練習!
押しスキャンコード懸念し、よりハンサム、より美しくヨ!いいえ世間の注目胡兄弟何かが胡兄ヨとの深い交流を続けることができ、言わないように!