使用TypeScript实现链表
- 使用泛型实现了数据结构的统一性
- 通过修饰符控制类中属性的访问权限
- 封装
LinkedList类实现链表中的各种方法
push()向链表末尾添加元素
getNodeAt()获取索引对应的节点
removeAt()移除对应索引的节点
indexOf()获取元素对应的第一个索引(表中有重复元素时只能获取第一个)
remove()移除对应元素的节点(表中有重复元素时只能移除第一个)
insert()在输入的索引位置插入节点
getHead()获取头节点
size()获取表长
isEmpty()判断表是否为空
clear()清空链表
单链表
export interface nodeType<T> {
element?: T
next: nodeType<T> | null
}
export class Node<T> implements nodeType<T> {
element: T
next: nodeType<T> | null = null
constructor( element: T ) {
this.element = element
}
}
export interface linkListType<T> {
push( element: T ): void
getNodeAt( index: number ): nodeType<T> | undefined
removeAt( index: number ): T | undefined
indexOf( element: T ): number | undefined
remove( element: T ): boolean
insert( element: T, index: number ): boolean
getHead(): nodeType<T> | null
size(): number
isEmpty(): boolean
clear(): void
}
export class LinkedList<T> implements linkListType<T> {
protected head: nodeType<T> | null = null
protected count: number = 0
push( element: T ): void {
const node = new Node<T>( element )
if ( !this.head ) {
this.head = node
} else {
let current = this.head
while ( current.next ) {
current = current.next
}
current.next = node
}
this.count++
}
getNodeAt( index: number ): nodeType<T> | undefined {
let node = this.head || undefined
if ( index >= 0 && index < this.count ) {
for ( let i = 0; i < index; i++ ) {
if ( node?.next )
node = node.next
}
return node
}
}
removeAt( index: number ): T | undefined {
let res: T | undefined = undefined
if ( index >= 0 && index < this.count ) {
if ( index === 0 ) {
let current = this.head
if ( current ) {
this.head = current.next
res = current.element
this.count--
}
} else {
let previous = this.getNodeAt( index - 1 )
let current = this.getNodeAt( index )
if ( previous && current ) {
previous.next = current.next
res = current.element
this.count--
}
}
}
return res
}
indexOf( element: T ): number | undefined {
let index: number | undefined = undefined
for ( let i = 0; i < this.count; i++ ) {
if ( this.getNodeAt( i )?.element === element ) index = i
}
return index
}
remove( element: T ): boolean {
let bool = false
const index = this.indexOf( element )
if ( index !== undefined && this.removeAt( index ) ) bool = true
return bool
}
insert( element: T, index: number ): boolean {
const node = new Node<T>( element )
let bool = false
if ( index >= 0 && index < this.count ) {
let current = this.head
if ( index === 0 && current ) {
this.head = node
node.next = current
bool = true
this.count++
} else {
let previous = this.getNodeAt( index - 1 )
let current = this.getNodeAt( index )
if ( previous && current ) {
previous.next = node
node.next = current
bool = true
this.count++
}
}
}
return bool
}
getHead(): nodeType<T> | null {
return this.head
}
size(): number {
return this.count
}
isEmpty(): boolean {
return this.count === 0
}
clear(): void {
this.head = null
this.count = 0
}
}
双向链表
import { LinkedList, linkListType, Node, nodeType } from './linkedList'
interface doublyNodeType<T> extends nodeType<T> {
prev: doublyNodeType<T> | null
next: doublyNodeType<T> | null
}
class DoublyNode<T> extends Node<T> implements doublyNodeType<T> {
prev: doublyNodeType<T> | null = null
next: doublyNodeType<T> | null = null
constructor( element: T ) {
super( element )
}
}
interface doublyLinkListType<T> extends linkListType<T> {
getNodeAt( index: number ): doublyNodeType<T> | undefined
getHead(): doublyNodeType<T> | null
getTail(): doublyNodeType<T> | null
}
class DoublyLinkedList<T> extends LinkedList<T> implements doublyLinkListType<T> {
protected tail: doublyNodeType<T> | null = null
protected head: doublyNodeType<T> | null = null
push( element: T ): void {
const node = new DoublyNode<T>( element )
if ( !this.head && !this.tail ) {
this.head = node
this.tail = node
this.count++
} else {
if ( this.tail ) {
this.tail.next = node
node.prev = this.tail
this.tail = node
this.count++
}
}
}
getNodeAt( index: number ): doublyNodeType<T> | undefined {
let node = this.head || undefined
if ( index >= 0 && index < this.count ) {
for ( let i = 0; i < index; i++ ) {
if ( node?.next )
node = node.next
}
return node
}
}
removeAt( index: number ): T | undefined {
let res: T | undefined = undefined
const current = this.getNodeAt( index )
if ( index >= 0 && index < this.count && current ) {
if ( index === 0 && current.next ) {
current.next.prev = null
this.head = current.next
this.count--
res = current.element
} else if ( index === 0 && !current.next && !current.prev ) {
this.head = null
this.tail = null
this.count--
res = current.element
} else if ( index !== 0 && index === this.count - 1 && current.prev ) {
current.prev.next = null
this.tail = current.prev
this.count--
res = current.element
} else if ( index !== 0 && current.prev && current.next ) {
current.prev.next = current.next
current.next.prev = current.prev
this.count--
res = current.element
}
}
return res
}
indexOf( element: T ): number | undefined {
return super.indexOf( element )
}
remove( element: T ): boolean {
let bool = false
const index = this.indexOf( element )
if ( index !== undefined && this.removeAt( index ) ) bool = true
return bool
}
insert( element: T, index: number ): boolean {
let bool = false
const node = new DoublyNode<T>( element )
if ( index >= 0 && index < this.count ) {
if ( index === 0 && this.tail && this.head ) {
this.head.prev = node
node.next = this.head
this.head = node
this.count++
bool = true
} else {
const previous = this.getNodeAt( index - 1 )
const current = this.getNodeAt( index )
if ( previous && current ) {
previous.next = node
node.next = current
current.prev = node
node.prev = previous
this.count++
}
}
}
return bool
}
getHead(): doublyNodeType<T> | null {
return this.head
}
getTail(): doublyNodeType<T> | null {
return this.tail
}
size(): number {
return super.size()
}
isEmpty(): boolean {
return super.isEmpty()
}
clear(): void {
super.clear()
this.tail = null
}
}
循环链表
import { LinkedList, linkListType, Node, nodeType } from './linkedList'
export class CircularLinkedList<T> extends LinkedList<T> implements linkListType<T> {
push( element: T ) {
const node = new Node( element )
const current = this.getNodeAt( this.size() - 1 )
if ( !this.head ) {
this.head = node
node.next = this.head
this.count++
} else if ( current ) {
current.next = node
node.next = this.head
this.count++
}
}
getNodeAt( index: number ): nodeType<T> | undefined {
return super.getNodeAt( index )
}
removeAt( index: number ): T | undefined {
const res = super.removeAt( index )
const tail = this.getNodeAt( this.size() - 1 )
if ( index === 0 && tail ) tail.next = this.head
return res
}
indexOf( element: T ): number | undefined {
return super.indexOf( element )
}
remove( element: T ): boolean {
let bool = false
const index = this.indexOf( element )
if ( index === 0 ) {
const tail = this.getNodeAt( this.size() - 1 )
const current = this.head
if ( index === 0 && tail && this.head && this.count !== 1 && current ) {
this.head = current.next
tail.next = this.head
} else if ( index === 0 && tail && this.head && this.count === 1 ) {
this.head = null
}
this.count--
bool = true
} else {
bool = super.remove( element )
}
return bool
}
insert( element: T, index: number ): boolean {
let res = super.insert( element, index )
if ( index === 0 ) {
const tail = this.getNodeAt( this.size() - 1 )
if ( tail ) tail.next = this.head
}
return res
}
getHead(): nodeType<T> | null {
return super.getHead()
}
size(): number {
return super.size()
}
isEmpty(): boolean {
return super.isEmpty()
}
clear() {
super.clear()
}
}