世界就像一个巨大的图书馆,我们读着别人,做着自己,等待被读。 :

ES6的JavaScript数据结构实现之链表

目的:ES6标准下的JS数据结构的一些实现代码。(作为记录和启发)

内容:链表和双向链表,循环链表,有序链表。(未完成,待继续)

所有源码在我的Github上(如果觉得不错记得给星鼓励我哦):ES6的JavaScript数据结构实现之链表

一、基础数据结构

1、链表

  1 class Node {
  2 constructor(element, next) {
  3 this.element = element;
  4 this.next = next;
  5 }
  6 }
  7 
  8 function defaultEquals(a, b) {
  9 return a === b;
 10 }
 11 
 12 class LinkedList {
 13 constructor(equalsFn = defaultEquals) {
 14 this.equalsFn = equalsFn;
 15 this.count = 0;
 16 this.head = undefined;
 17 }
 18 
 19 push(element){
 20 const node = new Node(element);
 21 let current;
 22 if (this.head == null){
 23 this.head = node;
 24 } else {
 25 current = this.head;
 26 while (current.next != null) {
 27 current = current.next;
 28 }
 29 current.next = node;
 30 }
 31 this.count++;
 32 }
 33 
 34 getElementAt(index) {
 35 if (index >= 0 && index <= this.count) {
 36 let node = this.head;
 37 for (let i = 0; i < index && node != null; i++) {
 38 node = node.next;
 39 }
 40 return node;
 41 }
 42 return undefined;
 43 }
 44 
 45 insert(element, index) {
 46 if (index >= 0 && index <= this.count) {
 47 const node = new Node(element);
 48 if (index ==0 ) {
 49 const current = this.head;
 50 node.next = current;
 51 this.head = node;
 52 } else {
 53 const previous = this.getElementAt(index - 1);
 54 node.next = previous.next;
 55 previous.next = node;
 56 }
 57 this.count++;
 58 return true;
 59 }
 60 return false;
 61 }
 62 
 63 removeAt(index) {
 64 if (index >= 0 && index < this.count) {
 65 let current = this.head;
 66 if (index == 0) {
 67 this.head = current.next; 
 68 }else {
 69 const previous = this.getElementAt(index - 1);
 70 current = previous.next;
 71 previous.next = current;
 72 
 73 }
 74 this.count--;
 75 return current.element;
 76 }
 77 return undefined;
 78 }
 79 
 80 remove(element) {
 81 const index = this.indexOf(element);
 82 return this.removeAt(index);
 83 }
 84 
 85 indexOf(element) {
 86 let current = this.head;
 87 for (let i = 0; i < this.count && current != null; i++) {
 88 if (this.equalsFn(element, current.element)) {
 89 return i;
 90 }
 91 current = current.next;
 92 } 
 93 return -1;
 94 }
 95 
 96 isEmpty() {
 97 return this.size() === 0;
 98 }
 99 
100 size() {
101 return this.count;
102 }
103 
104 getHead() {
105 return this.head;
106 }
107 
108 clear() {
109 this.head = undefined;
110 this.count = 0;
111 }
112 
113 toString() {
114 if (this.head == null) {
115 return '';
116 }
117 let objString = `${this.head.element}`;
118 let current = this.head.next;
119 for (let i = 1; i < this.size() && current != null; i++) {
120 objString = `${objString},${current.element}`;
121 current = current.next;
122 }
123 return objString;
124 }
125 }
126 
127 
128 const list = new LinkedList();
129 
130 console.log(list);
131 list.push(15);
132 console.log(list);
133 list.push(10);
134 list.push(5);
135 console.log(list);
136 list.removeAt(1);
137 console.log(list);
138 list.insert(4,1);
139 console.log(list);
140 console.log(list.indexOf(15));
141 console.log(list.indexOf(1));
142 list.remove(15);
143 console.log(list);
144 
145 LinkedList
LinkedList

  

2、双向链表

  1 class DoublyNode extends Node {
  2 constructor(element, next, prev) {
  3 super(element, next);
  4 this.prev = prev
  5 }
  6 }
  7 
  8 class DoublyLinkedList extends LinkedList {
  9 constructor(equalsFn = defaultEquals) {
 10 super (equalsFn);
 11 this.tail = undefined; 
 12 }
 13 push(element) {
 14 const node = new DoublyNode(element);
 15 if (this.head == null) {
 16 this.head = node;
 17 this.tail = node; // NEW
 18 } else {
 19 // attach to the tail node // NEW
 20 this.tail.next = node;
 21 node.prev = this.tail;
 22 this.tail = node;
 23 }
 24 this.count++;
 25 }
 26 insert(element, index) {
 27 if (index >= 0 && index <= this.count) {
 28 const node = new DoublyNode(element);
 29 let current = this.head;
 30 if (index == 0 ) {
 31 if(this.head == null) {
 32 this.head = node;
 33 this.tail = node;
 34 } else {
 35 node.next = this.head;
 36 this.head.prev = node;
 37 this.head = node;
 38 }
 39 } else if (index === this.count) {
 40 current = this.tail;
 41 current.next = node;
 42 node.prev = current;
 43 this.tail = node;
 44 } else {
 45 const previous = this.getElementAt(index - 1);
 46 current = previous.next; 
 47 node.next = current;
 48 previous.next = node;
 49 current.prev = node; 
 50 node.prev = previous;
 51 }
 52 this.count++;
 53 return true;
 54 }
 55 return false;
 56 }
 57 removeAt(index) {
 58 if (index >= 0 && index < this.count) {
 59 let current = this.head;
 60 if (index === 0) {
 61 this.head = this.head.next;
 62 if (this.count === 1) {
 63 this.tail = undefined;
 64 } else {
 65 this.head.prev = undefined;
 66 }
 67 } else if (index === this.count - 1) {
 68 current = this.tail;
 69 this.tail = current.prev;
 70 this.tail.next = undefined;
 71 } else {
 72 current = this.getElementAt(index);
 73 const previous = current.prev;
 74 previous.next = current.next;
 75 current.next.prev = previous;
 76 }
 77 this.count--;
 78 return current.element; 
 79 }
 80 return undefined;
 81 }
 82 indexOf(element) {
 83 let current = this.head;
 84 let index = 0;
 85 while (current != null) {
 86 if (this.equalsFn(element, current.element)) {
 87 return index;
 88 }
 89 index++;
 90 current = current.next;
 91 }
 92 return -1;
 93 }
 94 getHead() {
 95 return this.head;
 96 }
 97 getTail() {
 98 return this.tail;
 99 }
100 clear() {
101 super.clear();
102 this.tail = undefined;
103 }
104 toString() {
105 if (this.head == null) {
106 return '';
107 }
108 let objString = `${this.head.element}`;
109 let current = this.head.next;
110 while (current != null) {
111 objString = `${objString},${current.element}`;
112 current = current.next;
113 }
114 return objString;
115 }
116 inverseToString() {
117 // if (this.tail == null) {
118 // return '';
119 // }
120 let objString = `${this.tail.element}`;
121 let previous = this.tail.prev;
122 while (previous != null) {
123 objString = `${objString},${previous.element}`;
124 previous = previous.prev;
125 }
126 return objString;
127 }
128 }
129 
130 
131 const list = new DoublyLinkedList();
132 list.push(20);
133 console.log(list);
134 list.push(19);
135 list.push(18);
136 console.log(list);
137 list.insert(15, 1);
138 console.log(list);
139 list.removeAt(1);
140 console.log(list);
141 console.log(list.toString());
142 console.log(list.inverseToString());
DoublyNode

 

3、循环链表(以扩展上述普通链表Linkedlist为例)

 1 class CircularLinkedList extends LinkedList {
 2   constructor(equalsFn = defaultEquals) {
 3     super(equalsFn);
 4   }
 5   push(element) {
 6     const node = new Node(element);
 7     let current;
 8     if (this.head == null) {
 9       this.head = node;
10     } else {
11       current = this.getElementAt(this.size() - 1);
12       current.next = node;
13     }
14     // set node.next to head - to have circular list
15     node.next = this.head;
16     this.count++;
17   }
18   insert(element, index) {
19     if (index >= 0 && index <= this.count) {
20       const node = new Node(element);
21       let current = this.head;
22       if (index === 0) {
23         if (this.head == null) {
24           // if no node  in list
25           this.head = node;
26           node.next = this.head;
27         } else {
28           node.next = this.head;
29           current = this.getElementAt(this.size());
30           // update last element
31           this.head = node;
32           current.next = this.head;
33         }
34       } else {
35         const previous = this.getElementAt(index - 1);
36         node.next = previous.next;
37         previous.next = node;
38       }
39       this.count++;
40       return true;
41     }
42     return false;
43   }
44   removeAt(index) {
45     if (index >= 0 && index < this.count) {
46       let current = this.head;
47       if (index === 0) {
48         if (this.size() === 1) {
49           this.head = undefined;
50         } else {
51           const removed = this.head;
52           current = this.getElementAt(this.size() - 1);
53           this.head = this.head.next;
54           current.next = this.head;
55           current = removed;
56         }
57       } else {
58         // no need to update last element for circular list
59         const previous = this.getElementAt(index - 1);
60         current = previous.next;
61         previous.next = current.next;
62       }
63       this.count--;
64       return current.element;
65     }
66     return undefined;
67   }
68 }
69 
70 
71 const list = new CircularLinkedList();
72 
73 list.push(20);
74 console.log(list);
75 list.push(19);
76 list.push(18);
77 console.log(list);
78 list.insert(15, 0);
79 console.log(list);
80 list.removeAt(0);
81 console.log(list);
CircularLinkedList

 

4、有序链表

 1 class Node {
 2   constructor(element, next) {
 3     this.element = element;
 4     this.next = next;
 5   }
 6 }
 7 
 8 function defaultEquals(a, b) {
 9   return a === b;
10 }
11 
12 const Compare = {
13   LESS_THAN: -1,
14   BIGGER_THAN: 1,
15   EQUALS: 0
16 };
17 
18 function defaultCompare(a, b) {
19   if (a === b) {
20     return Compare.EQUALS;
21   }
22   return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN;
23 }
24 class SortedLinkedList extends LinkedList {
25   constructor(equalsFn = defaultEquals, compareFn = defaultCompare) {
26     super(equalsFn);
27     this.equalsFn = equalsFn;
28     this.compareFn = compareFn;
29   }
30   push(element) {
31     if (this.isEmpty()) {
32       super.push(element);
33     } else {
34       const index = this.getIndexNextSortedElement(element);
35       super.insert(element, index);
36     }
37   }
38   insert(element, index = 0) {
39     if (this.isEmpty()) {
40       return super.insert(element, index === 0 ? index : 0);
41     }
42     const pos = this.getIndexNextSortedElement(element);
43     return super.insert(element, pos);
44   }
45   getIndexNextSortedElement(element) {
46     let current = this.head;
47     let i = 0;
48     for (; i < this.size() && current; i++) {
49       const comp = this.compareFn(element, current.element);
50       if (comp === Compare.LESS_THAN) {
51         return i;
52       }
53       current = current.next;
54     }
55     return i;
56   }
57 }
58 
59 const list = new SortedLinkedList();
60 for (let i = 5; i > 0; i--) {
61   list.push(i);
62 }
63 console.log(list);
64 list.insert(1);
65 console.log(list);
SortedLinkedList

 

posted @ 2019-10-09 20:11  Secret_Wu  阅读(502)  评论(0编辑  收藏  举报