UNPKG

7.74 kBPlain TextView Raw
1import { Collection } from "../Collection";
2import CycleLinkList from "../cyclelinklist/CycleLinkList";
3import DoubleLinkList from "../doublelinklist/DoubleLinkList";
4import { LinkNode } from "./LinkNode";
5
6export class LinkList<T> extends Collection<LinkNode<T>> {
7 private headNode: LinkNode<T> = null;
8 private tailNode: LinkNode<T> = null;
9 private size = 0;
10 constructor() {
11 super();
12 }
13
14 public get Size(){
15 return this.size;
16 }
17
18 /**
19 * 向链表中追加一个节点
20 * @param value value为节点的值
21 * @returns LinkNode
22 */
23 public append(value: T): LinkNode<T>{
24 this.size++;
25 // 空链表时,设置头结点及尾节点
26 if (!this.headNode){
27 this.headNode = this.tailNode = new LinkNode(value);
28 return this.headNode;
29 }
30 // 只有一个节点时
31 if (this.headNode === this.tailNode){
32 this.tailNode = new LinkNode(value);
33 this.headNode.setNext(this.tailNode);
34 return this.headNode;
35 }
36 const tailNode = new LinkNode(value);
37 this.tailNode.setNext(tailNode);
38 this.tailNode = tailNode;
39 return this.headNode;
40 }
41
42 /**
43 * 向头部插入一个节点
44 * @param value value为节点的值
45 * @returns LinkNode
46 */
47 public prepend(value: T): LinkNode<T>{
48 // 空链表时
49 if (!this.headNode){
50 this.headNode = this.tailNode = new LinkNode(value);
51 }else{
52 this.headNode = new LinkNode(value, this.headNode);
53 }
54 this.size++;
55 return this.headNode;
56 }
57
58 private emptyList(){
59 this.headNode = this.tailNode = null;
60 this.size = 0;
61 }
62
63 /**
64 * 清空链表
65 */
66 public clear(){
67 this.emptyList();
68 }
69
70 /**
71 * 根据条件删除节点
72 * @param arg 如果arg是function,则调用arg,将当前节点value传入,否则将arg与当前节点value对比
73 * @returns boolean
74 */
75 public deleteNode(arg: any): boolean{
76 let temp: LinkNode<T> = this.headNode;
77 let result = false;
78 let prevNode: LinkNode<T>;
79 while (temp){
80 const match = typeof arg === "function" ? arg(temp.Value) : (temp.Value === arg);
81 if (match){
82 this.size--;
83 result = true;
84 // 删除第一个节点时
85 if (temp === this.headNode){
86 this.headNode = temp.Next;
87 }else if (temp === this.tailNode){
88 // 删除最后一个节点时
89 prevNode.setNext(null);
90 this.tailNode = prevNode;
91 }else{
92 prevNode.setNext(temp.Next);
93 }
94 }
95 // 如果删单向循环链表最后一个节点,跳出循环
96 // tslint:disable-next-line:curly
97 if (temp.Next && temp.Next === this.headNode)break;
98 // 如果删除节点后是空链表
99 if (this.size === 0){
100 this.emptyList();
101 break;
102 }
103 prevNode = temp;
104 temp = temp.Next;
105 }
106 return result;
107 }
108
109 /**
110 * 根据条件查找节点
111 * @param 如果arg是function,则调用arg,将当前节点value传入,否则将arg与当前节点value对比
112 * @returns LinkNode
113 */
114 public findNode(arg: any): LinkNode<T>{
115 let temp: LinkNode<T> = this.headNode;
116 let result: LinkNode<T>;
117 while (temp){
118 const match = typeof arg === "function" ? arg(temp.Value) : (temp.Value === arg);
119 if (match){
120 result = temp;
121 break;
122 }
123 temp = temp.Next;
124 }
125 return result;
126 }
127
128 /**
129 * 在某个节点后面插入一个节点
130 * @param value 要插入的节点值
131 * @param oriNode 在该节点后插入新节点
132 * @returns boolean
133 */
134 public insertAfter(value: T, oriNode: LinkNode<T>): boolean{
135 const newNode = new LinkNode(value);
136 if (oriNode){
137 const nextNode = oriNode.Next;
138 // 在尾节点后插入新节点
139 if (!nextNode || nextNode === this.headNode){
140 this.tailNode = newNode;
141 }
142 newNode.setNext(nextNode);
143 oriNode.setNext(newNode);
144 this.size++;
145 return true;
146 }
147 return false;
148 }
149
150 /**
151 * 获取头结点
152 * @returns LinkNode
153 */
154 public getHeadNode(): LinkNode<T>{
155 return this.headNode;
156 }
157
158 /**
159 * 获取尾节点
160 * @returns LinkNode
161 */
162 public getTailNode(): LinkNode<T>{
163 return this.tailNode;
164 }
165
166 /**
167 * 推出头节点
168 * @returns null | LinkNode
169 */
170 public shift(): LinkNode<T>{
171 if (this.size === 0){
172 return null;
173 }else if (this.size === 1){
174 this.tailNode = null;
175 }
176 const temp: LinkNode<T> = this.headNode;
177 this.headNode = temp.Next;
178 this.size--;
179 return temp;
180 }
181
182 /**
183 * 推出尾节点
184 * @returns null | LinkNode
185 */
186 public pop(): LinkNode<T>{
187 let temp: LinkNode<T> = this.headNode;
188 let result: LinkNode<T>;
189 let prevNode: LinkNode<T>;
190 if (this.size === 0){
191 return null;
192 }
193 // 链表只有一个节点时
194 if (this.size === 1){
195 result = this.headNode;
196 this.emptyList();
197 return result;
198 }
199 // 推出尾节点
200 while (temp){
201 const nextNode = temp.Next;
202 if (!nextNode || nextNode === this.headNode){
203 result = temp;
204 this.tailNode = prevNode;
205 prevNode.setNext(nextNode);
206 break;
207 }
208 prevNode = temp;
209 temp = nextNode;
210 }
211 this.size--;
212 return result;
213 }
214
215 protected __iterate(fn: (item: LinkNode<T>, index: number) => void): void {
216 let temp = this.headNode,
217 index = 0;
218 while (temp){
219 fn(temp, index);
220 index++;
221 const nextNode = temp.Next;
222 if (!nextNode || nextNode === this.headNode){
223 break;
224 }
225 temp = nextNode;
226 }
227 }
228
229 /**
230 * @returns string
231 */
232 public toString(){
233 return this.toArray().map(node => node.toString()).toString();
234 }
235
236 /**
237 * @param arr 数组转单向链表
238 * @returns LinkList
239 */
240 public static fromArray<K>(arr: Array<K>): LinkList<K> {
241 if (!arr){
242 return new LinkList<K>();
243 }
244 const linkList = new LinkList<K>();
245 arr.forEach(item => {
246 linkList.append(item);
247 });
248 return linkList;
249 }
250
251 /**
252 * @returns DoubleLinkList
253 */
254 public toDoubleLinkList(): DoubleLinkList<T>{
255 if (!this.headNode){
256 return new DoubleLinkList<T>();
257 }
258 const arr = this.toArray();
259 const doubleListList = new DoubleLinkList<T>();
260 arr.forEach(item => {
261 doubleListList.append(item.Value);
262 });
263 return doubleListList;
264 }
265
266 /**
267 * 单向链表转单向循环链表
268 * @returns CycleLinkList
269 */
270 public toCycleLinkList(): CycleLinkList<T>{
271 const cyclelinklist: CycleLinkList<T> = new CycleLinkList<T>();
272 this.toArray().forEach((node: LinkNode<T>) => {
273 cyclelinklist.append(node.Value);
274 });
275 return cyclelinklist;
276 }
277}
278
279export default LinkList;