1 | import {DoubleLinkListNode} from "../doublelinklist/ZKDoubleLinkListNode";
|
2 | import { IEnumerable } from "../interface/IEnumerable";
|
3 | import { IEnumerator } from "../interface/IEnumerator";
|
4 | export class DoubleLinkListCycle<T> implements IEnumerable<T>{
|
5 |
|
6 | private headNode: DoubleLinkListNode<T> = null;
|
7 | private tailNode: DoubleLinkListNode<T> = null;
|
8 | private size = 0;
|
9 | constructor() {
|
10 |
|
11 | }
|
12 |
|
13 | public get Size(){
|
14 | return this.size;
|
15 | }
|
16 |
|
17 | |
18 |
|
19 |
|
20 |
|
21 | public append(node: T){
|
22 | const currentNode = new DoubleLinkListNode(node);
|
23 | if (!this.tailNode){
|
24 | this.headNode = this.tailNode = currentNode;
|
25 | this.headNode.setNext(this.tailNode);
|
26 | this.tailNode.setPre(this.headNode);
|
27 | }else{
|
28 | currentNode.setPre(this.tailNode);
|
29 | currentNode.setNext(this.headNode);
|
30 | this.tailNode.setNext(currentNode);
|
31 | this.headNode.setPre(currentNode);
|
32 | this.tailNode = currentNode;
|
33 |
|
34 | }
|
35 | this.size++;
|
36 | return this;
|
37 | }
|
38 | |
39 |
|
40 |
|
41 |
|
42 | public prepend(node: T){
|
43 | const currentNode = new DoubleLinkListNode(node);
|
44 | if (!this.headNode){
|
45 | this.headNode = this.tailNode = currentNode;
|
46 | this.headNode.setNext(this.tailNode);
|
47 | this.tailNode.setPre(this.headNode);
|
48 | }else{
|
49 | this.headNode.setPre(currentNode);
|
50 | currentNode.setNext(this.headNode);
|
51 | currentNode.setPre(this.tailNode);
|
52 | this.tailNode.setNext(currentNode);
|
53 | this.headNode = currentNode;
|
54 | }
|
55 | this.size++;
|
56 | return this;
|
57 | }
|
58 |
|
59 | |
60 |
|
61 |
|
62 | private emptyList(){
|
63 | this.headNode = this.tailNode = null;
|
64 | this.size = 0;
|
65 | }
|
66 |
|
67 | |
68 |
|
69 |
|
70 |
|
71 | public shift(): DoubleLinkListNode<T>{
|
72 | const result = this.headNode;
|
73 | if (this.headNode === this.tailNode){
|
74 | this.emptyList();
|
75 | }else{
|
76 | this.headNode = this.headNode.next;
|
77 | this.headNode.setPre(this.tailNode);
|
78 | this.size--;
|
79 | }
|
80 | return result;
|
81 | }
|
82 |
|
83 | |
84 |
|
85 |
|
86 |
|
87 | public pop(): DoubleLinkListNode<T>{
|
88 | const result = this.tailNode;
|
89 | if (this.headNode === this.tailNode){
|
90 | this.emptyList();
|
91 | }else{
|
92 | this.tailNode = this.tailNode.Prev;
|
93 | this.tailNode.setNext(this.headNode);
|
94 | this.size--;
|
95 | }
|
96 | return result;
|
97 | }
|
98 |
|
99 | |
100 |
|
101 |
|
102 |
|
103 | public deleteNode(arg: any){
|
104 | const deleteArr: Array<number> = [];
|
105 | if (this.isEmpty()){
|
106 | return deleteArr;
|
107 | }
|
108 | let cycleNode: DoubleLinkListNode<T> = this.headNode;
|
109 | let index = 0;
|
110 | while (cycleNode){
|
111 | const match = typeof arg === "function" ? arg(cycleNode.value) : (cycleNode.value === arg);
|
112 | let deleteNode: DoubleLinkListNode<T> = null;
|
113 | if (match){
|
114 |
|
115 | if (this.headNode === this.tailNode){
|
116 | this.emptyList();
|
117 | break;
|
118 | }else{
|
119 |
|
120 |
|
121 | cycleNode.Prev.setNext(cycleNode.Next);
|
122 | cycleNode.Next.setPre(cycleNode.Prev);
|
123 | }
|
124 | deleteNode = cycleNode;
|
125 | deleteArr.push(index);
|
126 | }
|
127 | cycleNode = cycleNode.Next;
|
128 | const shouldBreak = cycleNode === this.headNode;
|
129 |
|
130 | if (deleteNode){
|
131 | if (deleteNode === this.headNode){
|
132 | this.headNode = deleteNode.Next;
|
133 | }
|
134 | if (deleteNode === this.tailNode){
|
135 | this.tailNode = deleteNode.Prev;
|
136 | }
|
137 | deleteNode.setNext(null);
|
138 | deleteNode.setPre(null);
|
139 | }
|
140 |
|
141 | if (shouldBreak){
|
142 | break;
|
143 | }
|
144 | index++;
|
145 | }
|
146 | }
|
147 |
|
148 | |
149 |
|
150 |
|
151 |
|
152 |
|
153 | public findNode(arg: any): DoubleLinkListNode<T>{
|
154 | let cycleNode: DoubleLinkListNode<T> = this.headNode;
|
155 | let result: DoubleLinkListNode<T> = null;
|
156 | while (cycleNode){
|
157 | const match = typeof arg === "function" ? arg(cycleNode.value) : (cycleNode.value === arg);
|
158 | if (match){
|
159 | result = cycleNode;
|
160 | break;
|
161 | }else if (cycleNode === this.tailNode){
|
162 | break;
|
163 | }
|
164 | cycleNode = cycleNode.Next;
|
165 | }
|
166 | return result;
|
167 | }
|
168 |
|
169 | |
170 |
|
171 |
|
172 |
|
173 | public getHeadNode(): DoubleLinkListNode<T>{
|
174 | return this.headNode;
|
175 | }
|
176 |
|
177 | |
178 |
|
179 |
|
180 |
|
181 | public getTailNode(): DoubleLinkListNode<T>{
|
182 | return this.tailNode;
|
183 | }
|
184 |
|
185 | |
186 |
|
187 |
|
188 |
|
189 | public isEmpty(): boolean{
|
190 | return !this.Size;
|
191 | }
|
192 |
|
193 | |
194 |
|
195 |
|
196 | public toString(){
|
197 | let temp = this.headNode;
|
198 | const arr: Array<DoubleLinkListNode<T>> = [];
|
199 | while (temp){
|
200 | arr.push(temp);
|
201 | temp = temp.Next;
|
202 | if (temp === this.headNode){
|
203 | break;
|
204 | }
|
205 | }
|
206 | return arr.toString();
|
207 | }
|
208 |
|
209 | getEnumerator(): IEnumerator<T> {
|
210 | let temp = this.getHeadNode();
|
211 | const enumerator = {
|
212 | next: () => {
|
213 | temp = temp.Next;
|
214 | enumerator.Current = {
|
215 | value: temp.value,
|
216 | done: false,
|
217 | };
|
218 | return enumerator;
|
219 | },
|
220 | Current: {
|
221 | value: temp.value,
|
222 | done: false,
|
223 | },
|
224 | };
|
225 | return enumerator;
|
226 | }
|
227 | }
|
228 |
|
229 | export default DoubleLinkListCycle;
|