场景如下:在开发中实现一个动态表单,能方便对表单项进行增删改操作,为了操作方便,给每一个节点增加pre和next属性用来指向前一个节点和后一个节点。于是想到用链表的数据结构来实现改功能(不用链表结构也能实现,只需要给每一个Node节点对象增加两个属性pre和next,在增删操作额外去维护这两个指针就行)
FormLinked.ts
ts
class FormItemNode<T extends {filed:string}> {
public data: T
public prev: FormItemNode<T> | null
public next: FormItemNode<T> | null
constructor(_data: T) {
this.data = _data
}
}
// T extends {filed:string} 需要根据filed属性判断 相等的依据
class FormLinked<T extends {filed:string}>{
/** 链表头节点 */
private head: FormItemNode<T> | null
/** 链表尾节点 */
private tail: FormItemNode<T> | null
/** 链表长度 */
private length = 0
get(position:number){
// 越界判断
if (position < 0 || position >= this.length) return null
if (position <= this.length / 2) {
// 获取对应的data
let current = this.head // 定义当前值为头节点
let index = 0 // 定义索引值为0
while (index++ < position) { // 循环找到需要的 position 对应位置的值
current = current.next
}
return current.data
} else {
let current = this.tail
let index = this.length - 1
while (index-- > position) {
current = current.prev
}
return current.data
}
}
indexOf(data:T | string){
// 定义变量
let current = this.head
let index = 0
// 查找current的data与传入值的data是否相等
while (current) {
if(typeof data === "string" && current.data.filed === data){
return index
}else if(typeof data !== "string" && current.data.filed === data.filed){
return index
}
index += 1
current = current.next
}
return -1
}
/**
* 链表尾部追加
* @param data
*/
append(data: T) {
// 1、根据data创建节点
let newNode = new FormItemNode(data)
// 2、判断添加的是否是第一个节点
if (this.length == 0) {
this.head = newNode
this.tail = newNode
} else {
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}
// 3、length + 1
this.length += 1
}
/**
* 插入到指定位置
* @param position 位置索引
* @param data
* @returns
*/
insert(position: number, data: T) {
// 越界判断
if (position < 0 || position > this.length) return false
// 根据 data 创建新的节点
let newNode = new FormItemNode(data)
// 判断原来的列表是否为空
if (this.length == 0) {
this.head = newNode
this.tail = newNode
} else {
if (position == 0) { // 插入到开头
this.head.prev = newNode
newNode.next = this.head
this.head = newNode
} else if (position == this.length) { // 插入到结尾
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
} else { // 插入到中间
let current = this.head
let index = 0
//找到插入位置
while (index++ < position) {
current = current.next
}
// 修改指针
newNode.next = current
newNode.prev = current.prev
current.prev.next = newNode
current.prev = newNode
}
}
// length + 1
this.length += 1
return true
}
/**
* 更新指定位置的数据
* @param position
* @param newData
* @returns
*/
update(position: number, newData: T) {
// 越界判断
if (position < 0 || position > this.length) return false
if (position <= this.length / 2) {
// 定义变量
let current = this.head
let index = 0
while (index++ < position) {
current = current.next
}
current.data = newData
return true
} else {
// 定义变量
let current = this.tail
let index = this.length - 1
while (index-- > position) {
current = current.prev
}
current.data = newData
return true
}
}
/**
* 删除指定数据的节点
* @param position
* @returns
*/
removeAt(position: number) {
// 越界判断
if (position < 0 || position > this.length) return null
var current = this.head
// 判断是否只有一个节点
if (this.length == 1) {
this.head = null
this.tail = null
} else {
if (position == 0) { // 判断删除的是否是第一个节点
this.head.next.prev = null
this.head = this.head.next
} else if (position == this.length - 1) { // 判断删除的是否是最后一个节点
current = this.tail
this.tail.prev.next = null
this.tail = this.tail.prev
} else { // 删除的是其他的节点
let index = 0
while (index++ < position) {
current = current.next
}
current.prev.next = current.next
current.next.prev = current.prev
}
}
// 长度减一
this.length -= 1
return current.data
}
/**
* 删除数据
* @param data
* @returns
*/
remove(data:T){
// 1、根据data获取下标值
let index = this.indexOf(data)
// 2、根据index删除对应位置的节点
return this.removeAt(index)
}
isEmpty(){
return this.length === 0
}
size(){
return this.length
}
getHead(){
return this.head
}
getTail(){
return this.tail
}
// 转换成数组
toArray(){
// 定义变量
let current = this.head
let index = 0
let arr:T[] = []
while (current) {
arr.push(current.data)
index += 1
current = current.next
}
return arr
}
}
export {FormItemNode,FormLinked}


本文作者:千寻
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!