1️⃣ 线性数据结构之数组

线性数据结构强调存储与顺序

2️⃣ 数组的特性

  1. 储存在物理空间上是连续的
  2. 底层的数组长度是不可变的
  3. 数组的变量,指向了数组的第一个元素的位置
  • 优点:查询性能好
  • 缺点:
    1. 因为空间必须得是连续的,所以如果数组比较大,当系统的空间碎片比较多的时候,容易存不下
    2. 因为数组的长度是固定的,所以数组的内容难以被添加和删除

2️⃣ 数组的实际操作

  1. // 声明一个数组
  2. let arr = [1, 2, 3, 4, 5];
  3. // 为数组最后一位添加一个数字 6
  4. arr.push(6);
  5. // 实际上是开辟了一个新的储存空间生成一个这样的数组 [1 , 2, 3, 4, 5, 6] 在赋值给 arr
  6. let arr = [1, 2, 3, 4, 5, 6];

1️⃣ 线性数据结构之链表

image.png

2️⃣ 链表的特点

  1. 空间上不是连续的
  2. 每存放一个值,都要多开销一个引用空间
  • 优点:
    1. 只要内存足够大,就能存的下,不用担心空间碎片的问题
    2. 链表的添加和删除非常的容易
  • 缺点:
    1. 查询速度慢 ( 指查询某个位置 )
    2. 链表每一个节点都需要创建指向 next 的引用,浪费一些空间,当节点内数据越多的时候,这部分多开销的内存影响越少
      1. // 链表结构
      2. var b = {
      3. value: 2,
      4. next: null,
      5. };
      6. var a = {
      7. value: 1,
      8. next: b,
      9. };
      10. console.log(a.next == b); // true

2️⃣ 创建一个单项链表

  1. // 创建一个链表
  2. function Node(value) {
  3. this.value = value;
  4. this.next = null;
  5. }
  6. var a = new Node(1);
  7. var b = new Node(2);
  8. var c = new Node(3);
  9. a.next = b;
  10. b.next = c;
  11. c.next = null;
  12. console.log(a.value); // 1
  13. console.log(a.next.value); // 2
  14. console.log(a.next.next.value); // 3

2️⃣ 创建一个双向链表

双向链表的优点,无论给出哪一个节点,都能对整个链表进行遍历
双向链表的缺点,对耗费一个引用空间,而且构建起来比较复杂

  1. function Node(value) {
  2. this.value;
  3. this.next = null;
  4. this.pre = null;
  5. }
  6. var node1 = new Node(1);
  7. var node2 = new Node(2);
  8. var node3 = new Node(3);
  9. var node4 = new Node(4);
  10. var node5 = new Node(5);
  11. node1.next = node2;
  12. node2.pre = node1;
  13. node2.next = node3;
  14. node3.pre = node2;
  15. node3.next = node4;
  16. node4.pre = node3;
  17. node4.next = node5;
  18. node5.pre = node4;

1️⃣ 线性数据结构的遍历

遍历:将一个集合中的每一个元素进行获取并查看

  1. // 创建一个链表
  2. function Node(value) {
  3. this.value = value;
  4. this.next = null;
  5. }
  6. var a = new Node(1);
  7. var b = new Node(2);
  8. var c = new Node(3);
  9. a.next = b;
  10. b.next = c;
  11. c.next = null;
  12. function bianli(root) {
  13. var temp = root;
  14. while (true) {
  15. if (temp != null) {
  16. console.log(temp.value, temp);
  17. // 输出
  18. // 1 Node {
  19. // value: 1,
  20. // next: Node { value: 2, next: Node { value: 3, next: null } }
  21. // }
  22. // 2 Node { value: 2, next: Node { value: 3, next: null } }
  23. // 3 Node { value: 3, next: null }
  24. } else {
  25. break;
  26. }
  27. temp = temp.next;
  28. }
  29. }
  30. bianli(a);

1️⃣ 线性数据结构的递归

  1. function Node(value) {
  2. this.value = value;
  3. this.next = null;
  4. }
  5. var a = new Node(1);
  6. var b = new Node(2);
  7. var c = new Node(3);
  8. a.next = b;
  9. b.next = c;
  10. c.next = null;
  11. function bianli(node) {
  12. if (node == null) return;
  13. console.log(node.value);
  14. // 输出
  15. // 1
  16. // 2
  17. // 3
  18. bianli(node.next)
  19. }
  20. bianli(a);

1️⃣ 链表的逆置

  1. function Node(value) {
  2. this.value = value;
  3. this.next = null;
  4. }
  5. var a = new Node(1);
  6. var b = new Node(2);
  7. var c = new Node(3);
  8. a.next = b;
  9. b.next = c;
  10. c.next = null;
  11. // 链表递归函数
  12. function bianli(node) {
  13. if (node == null) return;
  14. console.log(node.value);
  15. bianli(node.next)
  16. }
  17. // 链表逆置函数
  18. function nizhi(node) {
  19. if (node.next.next == null) { // 代表当前节点事倒数第二个节点
  20. node.next.next = node; // 让最后一个节点指向自己 ( 倒数第二个节点 )
  21. return node.next;
  22. } else {
  23. var result = nizhi(node.next);
  24. node.next.next = node;
  25. node.next = null;
  26. return result;
  27. }
  28. }
  29. bianli(a);
  30. /*
  31. * 1
  32. * 2
  33. * 3
  34. */
  35. nizhi(a) // 执行链表逆置的函数
  36. bianli(c);
  37. /*
  38. * 3
  39. * 2
  40. * 1
  41. */