first commit

This commit is contained in:
宫欣海
2025-02-20 11:27:28 +08:00
commit 68090ca38d
91 changed files with 9915 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
/**
* @Author: Gongxh
* @Date: 2024-12-07
* @Description: 二叉堆(默认最小堆) 支持最大堆和最小堆
*/
export abstract class HeapNode {
public index: number;
public abstract lessThan(other: HeapNode): boolean;
}
export class BinaryHeap<T extends HeapNode> {
private _nodes: Array<T>;
private _size: number;
private _capacity: number;
constructor(capacity: number) {
this._size = 0;
this._capacity = capacity <= 0 ? 4 : capacity;
this._nodes = new Array<T>(this._capacity);
}
/**
* 清空
*/
public clear(): void {
this._size = 0;
}
/**
* 获取节点
* @param index 节点索引
*/
public get(index: number): T {
return this._nodes[index];
}
/**
* 获取顶部节点
*/
public top(): T {
return this._nodes[0];
}
/**
* 是否包含节点
* @param node 节点
*/
public contains(node: T): boolean {
return node.index >= 0 && node.index < this._size;
}
/**
* Push节点
* @param node 节点
*/
public push(node: T): void {
const size = ++this._size;
if (size > this._capacity) {
this._capacity = this._nodes.length *= 2;
}
this._sortUp(node, size - 1);
}
/**
* Pop节点
* @returns
*/
public pop(): T {
if (this._size == 0) {
return null;
}
const nodes = this._nodes;
const node = nodes[0];
node.index = -1;
nodes[0] = null;
const size = --this._size;
if (size > 0) {
const finalNode = nodes[size];
nodes[size] = null;
this._sortDown(finalNode, 0);
}
return node;
}
/**
* 移除节点
* @param node 要移除的节点
*/
public remove(node: T): void {
if (!this.contains(node)) {
return;
}
const size = --this._size;
const nodes = this._nodes;
const newNode = (nodes[node.index] = nodes[size]);
newNode.index = node.index;
nodes[size] = null;
this.update(newNode);
node.index = -1;
}
/**
* 更新节点
* @param node 要更新的节点
*/
public update(node: T): boolean {
if (!this.contains(node)) {
return false;
}
const index = node.index;
const nodes = this._nodes;
if (index > 0 && nodes[index].lessThan(nodes[this._parent(index)])) {
this._sortUp(nodes[index], index);
} else {
this._sortDown(nodes[index], index);
}
return true;
}
private _parent(index: number): number {
return (index - 1) >> 1;
}
public get count(): number {
return this._size;
}
public get empty(): boolean {
return this._size == 0;
}
private _sortUp(node: T, index: number): void {
let parentIndex = this._parent(index);
const nodes = this._nodes;
while (index > 0 && node.lessThan(nodes[parentIndex])) {
nodes[parentIndex].index = index;
nodes[index] = nodes[parentIndex];
index = parentIndex;
parentIndex = this._parent(parentIndex);
}
node.index = index;
nodes[index] = node;
}
private _sortDown(node: T, index: number): void {
let childIndex = (index << 1) + 1;
const nodes = this._nodes;
const size = this._size;
while (childIndex < size) {
let newParent = node;
// left
if (nodes[childIndex].lessThan(newParent)) {
newParent = nodes[childIndex];
}
// right
if (childIndex + 1 < size && nodes[childIndex + 1].lessThan(newParent)) {
++childIndex;
newParent = nodes[childIndex];
}
if (node == newParent) {
break;
}
// swap down
newParent.index = index;
nodes[index] = newParent;
index = childIndex;
childIndex = (childIndex << 1) + 1;
}
node.index = index;
nodes[index] = node;
}
}

View File

@@ -0,0 +1,301 @@
function defaultEquals<T>(a: T, b: T): boolean {
return a === b;
}
/** 单链表结结构节点 */
export class LinkedNode<T> {
public element: T;
public next: LinkedNode<T>; // 下一项元素的指针
constructor(element: T) {
this.element = element;
this.next = undefined;
}
}
/** 双向链表结结构节点 */
export class DoublyNode<T> extends LinkedNode<T> {
public prev: DoublyNode<T>; // 上一项元素的指针
public next: DoublyNode<T>; // 下一元素的指针(重新定义下一个元素的类型)
constructor(element: T) {
super(element);
this.prev = undefined;
}
}
/** 单向链表 */
export class LinkedList<T> {
protected _equalsFn: (a: T, b: T) => boolean;
protected _count: number;
protected _head: LinkedNode<T>;
/**
* create
* @param equalsFn 比较是否相等(支持自定义)
*/
constructor(equalsFn?: (a: T, b: T) => boolean) {
this._equalsFn = equalsFn || defaultEquals;
this._count = 0;
this._head = undefined;
}
/** 向链表尾部添加元素 */
public push(element: T): void {
const node = new LinkedNode<T>(element);
let current: LinkedNode<T>;
if (this._head === undefined) {
this._head = node;
} else {
current = this._head;
while (current.next !== undefined) {
current = current.next;
}
current.next = node;
}
this._count++;
}
/**
* 在链表的指定位置插入一个元素。
* @param element 要插入的元素。
* @param index 插入位置的索引从0开始计数。
* @returns 如果插入成功返回true否则返回false。
*/
public insert(element: T, index: number): boolean {
if (index >= 0 && index <= this._count) {
const node = new LinkedNode<T>(element);
if (index === 0) {
const current = this._head;
node.next = current;
this._head = node;
} else {
const previous = this.getElementAt(index - 1);
const current = previous.next;
node.next = current;
previous.next = node;
}
this._count++;
return true;
}
return false;
}
/**
* 获取链表中指定位置的元素,如果不存在返回 underfined
* @param index
*/
public getElementAt(index: number): LinkedNode<T> {
if (index >= 0 && index <= this._count) {
let node = this._head;
for (let i = 0; i < index && node !== undefined; i++) {
node = node.next;
}
return node;
}
return undefined;
}
/**
* 从链表中移除一个元素
* @param element
*/
public remove(element: T): T {
return this.removeAt(this.indexOf(element));
}
/**
* 从链表的特定位置移除一个元素
* @param index
*/
public removeAt(index: number): T {
if (index >= 0 && index < this._count) {
let current = this._head;
if (index === 0) {
this._head = current.next;
} else {
const previous = this.getElementAt(index - 1);
current = previous.next;
previous.next = current.next;
}
this._count--;
current.next = undefined;
return current.element;
}
return undefined;
}
/**
* 返回元素在链表中的索引,如果没有则返回-1
* @param element
*/
public indexOf(element: T): number {
let current = this._head;
for (let i = 0; i < this._count && current !== undefined; i++) {
if (this._equalsFn(element, current.element)) {
return i;
}
current = current.next;
}
return -1;
}
public clear(): void {
this._head = undefined;
this._count = 0;
}
public getHead(): LinkedNode<T> {
return this._head;
}
public isEmpty(): boolean {
return this.size() === 0;
}
public size(): number {
return this._count;
}
public toString(): string {
if (this._head === undefined) {
return "";
}
let objString = `${this._head.element}`;
let current = this._head.next;
for (let i = 0; i < this.size() && current !== undefined; i++) {
objString = `${objString},${current.element}`;
current = current.next;
}
return objString;
}
}
/** 双向链表 */
export class DoublyLinkedList<T> extends LinkedList<T> {
protected _head: DoublyNode<T>; // 重新定义 head 类型
protected _tail: DoublyNode<T>;
/**
* create
* @param equalsFn 比较是否相等(支持自定义)
*/
constructor(equalsFn?: (a: T, b: T) => boolean) {
super(equalsFn);
this._tail = undefined;
}
/**
* 向链表尾部添加元素
* @param element
*/
public push(element: T): void {
this.insert(element, this._count);
}
/**
* 向链表指定位置添加元素
* @param element
* @param index
*/
public insert(element: T, index: number): boolean {
if (index >= 0 && index <= this._count) {
const node = new DoublyNode<T>(element);
let current = this._head;
if (index === 0) {
if (this._head === undefined) {
this._head = node;
this._tail = node;
} else {
node.next = current;
current.prev = node;
this._head = node;
}
} else if (index === this._count) {
current = this._tail;
current.next = node;
node.prev = current;
this._tail = node;
} else {
const previous = this.getElementAt(index - 1);
current = previous.next;
node.next = current;
previous.next = node;
current.prev = node;
node.prev = previous;
}
this._count++;
return true;
}
return false;
}
/**
* 从链表的特定位置移除一个元素
* @param index
*/
public removeAt(index: number): T {
if (index >= 0 && index < this._count) {
let current = this._head;
if (index === 0) {
this._head = current.next;
if (this._count === 1) {
this._tail = undefined;
} else {
this._head.prev = undefined;
}
} else if (index === this._count - 1) {
current = this._tail;
this._tail = current.prev;
this._tail.next = undefined;
} else {
current = this.getElementAt(index);
const previous = current.prev;
previous.next = current.next;
current.next.prev = previous;
}
this._count--;
current.next = undefined;
current.prev = undefined;
return current.element;
}
return null;
}
/**
* 获取链表中指定位置的元素,如果不存在返回 null
* @param index
*/
public getElementAt(index: number): DoublyNode<T> {
if (index >= 0 && index <= this._count) {
if (index > this._count * 0.5) {
// 从后向前找
let node = this._tail;
for (let i = this._count - 1; i > index && node !== undefined; i--) {
node = node.prev;
}
return node;
} else {
// 从前向后找
let node = this._head;
for (let i = 0; i < index && node !== undefined; i++) {
node = node.next;
}
return node;
}
}
return undefined;
}
public getHead(): DoublyNode<T> {
return this._head;
}
public getTail(): DoublyNode<T> {
return this._tail;
}
public clear(): void {
this._head = undefined;
this._tail = undefined;
this._count = 0;
}
}

View File

@@ -0,0 +1,42 @@
import { DoublyLinkedList } from "./LinkedList";
export class Stack<T> {
private _items: DoublyLinkedList<T>;
constructor(equalsFn?: (a: T, b: T) => boolean) {
this._items = new DoublyLinkedList<T>(equalsFn);
}
public push(element: T): void {
this._items.push(element);
}
public pop(): T {
if (this.isEmpty()) {
return undefined;
}
return this._items.removeAt(this.size() - 1);
}
public peek(): T {
if (this.isEmpty()) {
return undefined;
}
return this._items.getTail().element;
}
public size(): number {
return this._items.size();
}
public isEmpty(): boolean {
return this._items.isEmpty();
}
public clear(): void {
this._items.clear();
}
public toString(): string {
return this._items.toString();
}
}