数据结构与算法--基础链表(TypeScript)

定义链表

LinkedList.ts

interface ILinkedList<T> {
  indexOf(value: T): number;
  append(value: T): void;
  remove(value: T): T | null;
  insert(value: T, position: number): boolean;
  removeAt(position: number): T | null;
  get(position: number): T | null;
  update(position: number, element: T): boolean;
  isEmpty(): boolean;
  traverse(): void;
  get length(): number;
}

class ListNode<T> {
  val: T;
  next: ListNode<T> | null;
  constructor(val: T, next?: ListNode<T> | null) {
    this.val = val;
    this.next = next == undefined ? null : next;
  }
}

class LinkedList<T> implements ILinkedList<T> {
  head: ListNode<T> | null = null;
  size: number = 0;
  get length(): number {
    return this.size;
  }
  indexOf(value: T): number {
    let index = 0;
    let current = this.head;
    while (current) {
      if (current.val == value) {
        return index;
      }
      current = current.next;
      index++;
    }
    return -1;
  }
  append(value: T): void {
    // 创建一个新节点
    const newNode = new ListNode<T>(value);
    // 将节点追加到链表后
    if (!this.head) {
      // 如果链表为空
      this.head = newNode;
    } else {
      // 链表不为空,找到最后一个元素(最后一个节点的next为)
      let current = this.head;
      while (current.next) {
        current = current.next;
      }
      current.next = newNode;
    }
    this.size++;
  }
  insert(value: T, position: number): boolean {
    if (position < 0 || position > this.size) return false;
    // 创建节点
    const newNode = new ListNode<T>(value);
    if (position == 0) {
      newNode.next = this.head;
      this.head = newNode;
    } else {
      // 找到position对应节点的前一个节点
      let index = 0;
      let previous = this.head;
      while (index++ < position - 1) {
        previous = previous!.next;
      }
      newNode.next = previous!.next;
      previous!.next = newNode;
    }
    this.size++;
    return true;
  }
  // 空值合并运算符( ?? )是一个逻辑操作符,如果左侧的表达式为 null 或者 undefined 时,返回其右侧表达式,否则返回左侧表达式
  removeAt(position: number): T | null {
    if (position < 0 || position >= this.size) return null;
    let removeVal: T | null = null;
    if (position == 0) {
      removeVal = this.head?.val ?? null;
      this.head = this.head?.next ?? null;
    } else {
      // 找到position对应节点的前一个节点
      let index: number = 0;
      let previous = this.head;
      while (index++ < position - 1) {
        previous = previous!.next;
      }
      // 因为之前对position进行范围判断,所以previous和previous.next一定存在
      removeVal = previous!.next!.val;
      previous!.next = previous!.next!.next ?? null;
    }
    this.size--;
    return removeVal;
  }
  get(position: number): T | null {
    if (position < 0 || position >= this.size) return null;
    let index = 0;
    let current = this.head;
    while (index++ < position) {
      current = current!.next;
    }
    return current!.val;
  }
  update(position: number, element: T): boolean {
    if (position < 0 || position >= this.size) return false;
    let index = 0;
    let current = this.head;
    while (index++ < position) {
      current = current!.next;
    }
    current!.val = element;
    return true;
  }
  remove(value: T): T | null {
    const index = this.indexOf(value);
    return this.removeAt(index);
  }
  isEmpty(): boolean {
    return this.size == 0;
  }
  traverse(): void {
    let values: T[] = [];
    let current = this.head;
    while (current) {
      values.push(current.val);
      current = current.next;
    }
    console.log(values.join("->"));
  }
}

// test
const linkedList = new LinkedList<string>();
linkedList.append("aa");
linkedList.append("bb");
linkedList.append("cc");
linkedList.traverse();
linkedList.insert("head", 0);
linkedList.insert("middle", 2);
linkedList.insert("end", 5);
linkedList.traverse();
console.log(linkedList.removeAt(0));
linkedList.traverse();
console.log(linkedList.removeAt(3));
linkedList.traverse();
console.log(linkedList.removeAt(3));
linkedList.traverse();
console.log(linkedList.get(0));
console.log(linkedList.get(1));
console.log(linkedList.get(2));
linkedList.update(1, "11");
linkedList.traverse();
console.log(linkedList.indexOf("11"));
console.log(linkedList.isEmpty());
console.log(linkedList.remove("11"));
console.log(linkedList.remove("aa"));
console.log(linkedList.remove("bb"));
console.log(linkedList.isEmpty());
linkedList.traverse();

应用

链表反转

class ListNode<T> {
  val: T;
  next: ListNode<T> | null;
  constructor(val: T, next?: ListNode<T> | null) {
    this.val = val;
    this.next = next == undefined ? null : next;
  }
}
// 反转链表
function ReverseLinkedList(head: ListNode<number> | null): ListNode<number> | null {
  // 一个节点或者无节点可以直接返回
  if (head == null || head.next == null) return head;
  let cur: ListNode<number> | null = head;
  let pre: ListNode<number> | null = null;
  while (cur) {
    let next = cur.next; // 记录cur的下一个节点
    cur.next = pre; // 反方向链接 (以头节点为例,此时头结点已经摘出来,它的下个节点的信息保存在next中)
    // 将pre 和 cur依次向后移动
    pre = cur;
    cur = next;
  }
  return pre;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值