Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6e0cb70

Browse files
committedSep 9, 2023
AV-07: Linked list updated with delete node with arrow
1 parent 40cb195 commit 6e0cb70

File tree

1 file changed

+368
-356
lines changed

1 file changed

+368
-356
lines changed
 
+368-356
Original file line numberDiff line numberDiff line change
@@ -1,376 +1,388 @@
11
<template>
2-
<div>
3-
<h1>Linked List</h1>
4-
<div ref="circleContainer"></div>
5-
<div v-if="showSuccessResult" class="success-message">
6-
Searched item {{ targetValue }} found at: "{{ result }}"
7-
</div>
8-
9-
<div v-if="showFailureResult" class="fail-message">
10-
Searched item not found!
11-
</div>
12-
<hr>
13-
<form v-if="showInputForm" @submit.prevent="insertFormSubmitAction">
14-
<input v-model="insertedValue" type="number" name="Number" placeholder="Enter Number">
15-
<button type="submit">Add</button>
16-
</form>
17-
<form v-if="showSearchForm" @submit.prevent="searchIntoLinkedList">
18-
<input v-model="targetValue" type="number" name="Number" placeholder="Enter Number">
19-
<button type="submit">Search</button>
20-
</form>
21-
<form v-if="showDeleteForm" @submit.prevent="removeItemFromLinkedList">
22-
<input v-model="targetValue" type="number" name="Number" placeholder="Enter Number">
23-
<button type="submit">Delete</button>
24-
</form>
25-
<button @click="toggleSearchForm">Search</button>
26-
<button @click="toggleInsertForm">Insert</button>
27-
<button @click="toggleDeleteForm">Delete Node</button>
2+
<div>
3+
<h1>Linked List</h1>
4+
<div ref="circleContainer"></div>
5+
<div v-if="showSuccessResult" class="success-message">
6+
Searched item {{ targetValue }} found at: "{{ result }}"
287
</div>
8+
9+
<div v-if="showFailureResult" class="fail-message">
10+
Searched item not found!
11+
</div>
12+
<hr>
13+
<form v-if="showInputForm" @submit.prevent="insertFormSubmitAction">
14+
<input v-model="insertedValue" type="number" name="Number" placeholder="Enter Number">
15+
<button type="submit">Add</button>
16+
</form>
17+
<form v-if="showSearchForm" @submit.prevent="searchIntoLinkedList">
18+
<input v-model="targetValue" type="number" name="Number" placeholder="Enter Number">
19+
<button type="submit">Search</button>
20+
</form>
21+
<form v-if="showDeleteForm" @submit.prevent="removeItemFromLinkedList">
22+
<input v-model="targetValue" type="number" name="Number" placeholder="Enter Number">
23+
<button type="submit">Delete</button>
24+
</form>
25+
<button @click="toggleSearchForm">Search</button>
26+
<button @click="toggleInsertForm">Insert</button>
27+
<button @click="toggleDeleteForm">Delete Node</button>
28+
</div>
2929
</template>
3030

3131
<script>
32-
class Node {
33-
constructor(data) {
34-
this.data = data;
35-
this.next = null;
36-
this.element = {};
37-
}
32+
class Node {
33+
constructor(data) {
34+
this.data = data;
35+
this.next = null;
36+
this.element = {};
37+
}
38+
}
39+
40+
class LinkedList {
41+
constructor() {
42+
this.head = null;
43+
}
44+
45+
append(data, element) {
46+
const newNode = new Node(data);
47+
newNode.element.circle = element.circle.circle;
48+
newNode.element.text = element.circle.text;
49+
if (!this.head) {
50+
newNode.element.arrow = element.arrow;
51+
this.head = newNode;
52+
return;
3853
}
3954
40-
class LinkedList {
41-
constructor() {
42-
this.head = null;
55+
let current = this.head;
56+
while (current.next) {
57+
current = current.next;
58+
}
59+
current.element.arrow = element.arrow;
60+
current.next = newNode;
61+
}
62+
63+
display() {
64+
let current = this.head;
65+
while (current) {
66+
console.log(current.data);
67+
current = current.next;
68+
}
69+
}
70+
}
71+
72+
73+
import * as d3 from 'd3';
74+
75+
export default {
76+
name: "Linked-List",
77+
data() {
78+
return {
79+
linkedList: undefined,
80+
result: "",
81+
showSuccessResult: false,
82+
showFailureResult: false,
83+
xAxis: 20,
84+
arrowXAxis: 0,
85+
circleRadius: 5,
86+
elements: [],
87+
circleContainer: undefined,
88+
showInputForm: false,
89+
showSearchForm: false,
90+
showDeleteForm: false,
91+
targetValue: null,
92+
insertedValue: null,
93+
}
94+
},
95+
96+
methods: {
97+
createContainer() {
98+
this.circleContainer = d3.select(this.$refs.circleContainer)
99+
.append('svg')
100+
.attr('width', 500)
101+
.attr('height', 200);
102+
},
103+
104+
change() {
105+
for (const element of this.elements) {
106+
element.circle.transition()
107+
.duration(1000) // Animation duration in milliseconds
108+
.attr('fill', 'rgba(0, 255, 0, 0.8)');
109+
}
110+
},
111+
112+
toggleInsertForm() {
113+
this.showSuccessResult = false;
114+
this.showFailureResult = false;
115+
this.showInputForm = !this.showInputForm;
116+
this.hideDeleteForm();
117+
this.hideSearchForm();
118+
},
119+
120+
toggleSearchForm() {
121+
this.showSuccessResult = false;
122+
this.showFailureResult = false;
123+
this.showSearchForm = !this.showSearchForm;
124+
this.hideDeleteForm();
125+
this.hideInsertForm();
126+
},
127+
128+
toggleDeleteForm() {
129+
this.showSuccessResult = false;
130+
this.showFailureResult = false;
131+
this.hideInsertForm();
132+
this.hideSearchForm();
133+
this.showDeleteForm = !this.showDeleteForm;
134+
},
135+
136+
hideDeleteForm() {
137+
this.showDeleteForm = false;
138+
},
139+
hideInsertForm() {
140+
this.showInputForm = false;
141+
},
142+
hideSearchForm() {
143+
this.showSearchForm = false;
144+
},
145+
146+
insertFormSubmitAction() {
147+
if (this.insertedValue > 0) {
148+
149+
this.appendIntoLinkedList(this.insertedValue);
150+
this.showInputForm = false;
151+
this.insertedValue = null;
152+
} else {
153+
console.error("You've added negative number");
154+
}
155+
},
156+
157+
createCircle(num, createArrow) {
158+
159+
const finalRadius = 20;
160+
161+
const circle = this.circleContainer.append('circle')
162+
.attr('cx', this.xAxis)
163+
.attr('cy', 100)
164+
.attr('r', this.circleRadius)
165+
.attr('fill', 'rgba(0, 0, 255, 0.5)')
166+
.attr('opacity', .5);
167+
circle.transition()
168+
.duration(1000) // Animation duration in milliseconds
169+
.attr('r', finalRadius);
170+
171+
const text = this.circleContainer.append('text')
172+
.attr('x', this.xAxis)
173+
.attr('y', 100)
174+
.attr('dy', '.4em') // Vertical alignment adjustment
175+
.attr('text-anchor', 'middle') // Horizontal alignment
176+
.text(num);
177+
if (createArrow) {
178+
this.createArrow(this.xAxis + 70);
179+
}
180+
this.elements.push({circle: circle, text: text});
181+
182+
this.xAxis += this.circleRadius * 20;
183+
184+
return {circle: circle, text: text};
185+
186+
// this.circleContainer.append('circle')
187+
// .attr('cx', 90)
188+
// .attr('cy', 100)
189+
// .attr('r', finalRadius)
190+
// .attr('fill', 'red');
191+
//
192+
//
193+
},
194+
195+
createArrow(groupX) {
196+
const arrowLength = 20;
197+
const arrowY = 100;
198+
199+
const linesGroup = this.circleContainer.append('g')
200+
.attr('transform', `translate(${groupX}, 0)`); // Set the group's x position
201+
202+
linesGroup.append('line')
203+
.attr('x1', -arrowLength - 20) // Relative to the group's x position
204+
.attr('y1', arrowY)
205+
.attr('x2', 0) // Relative to the group's x position
206+
.attr('y2', arrowY)
207+
.attr('stroke', 'black')
208+
.attr('stroke-width', 2);
209+
210+
linesGroup.append('line')
211+
.attr('x1', -10) // Relative to the group's x position
212+
.attr('y1', arrowY - 5)
213+
.attr('x2', -arrowLength + 20) // Relative to the group's x position
214+
.attr('y2', arrowY)
215+
.attr('stroke', 'black')
216+
.attr('stroke-width', 2);
217+
218+
linesGroup.append('line')
219+
.attr('x1', -10) // Relative to the group's x position
220+
.attr('y1', arrowY + 5)
221+
.attr('x2', -arrowLength + 20) // Relative to the group's x position
222+
.attr('y2', arrowY)
223+
.attr('stroke', 'black')
224+
.attr('stroke-width', 2);
225+
226+
return linesGroup;
227+
},
228+
229+
appendIntoLinkedList(num, pos) {
230+
if (!pos) {
231+
const circle = this.createCircle(num);
232+
let arrow;
233+
if (this.linkedList.head) {
234+
arrow = this.createArrow((this.xAxis - this.circleRadius * 40) + 70);
43235
}
44236
45-
append(data, element) {
46-
const newNode = new Node(data);
47-
newNode.element.circle = element.circle.circle;
48-
newNode.element.text = element.circle.text;
49-
if (!this.head) {
50-
newNode.element.lines = element.lines;
51-
this.head = newNode;
52-
return;
53-
}
237+
this.linkedList.append(num, {circle: circle, arrow: arrow});
238+
}
239+
},
54240
55-
let current = this.head;
56-
while (current.next) {
57-
current = current.next;
58-
}
59-
current.element.lines = element.lines;
60-
current.next = newNode;
61-
}
62241
63-
display() {
64-
let current = this.head;
65-
while (current) {
66-
console.log(current.data);
67-
current = current.next;
68-
}
242+
deleteNode(node, cx, x, arrowX) {
243+
if (node) {
244+
const currentCircleXAxis = parseFloat(node.element.circle.attr('cx'));
245+
const currentTextX = parseFloat(node.element.text.attr('x'));
246+
let nextArrow;
247+
if (node.element.arrow) {
248+
nextArrow = parseFloat(node.element.arrow.attr('transform').split('(')[1].split(',')[0]);
69249
}
70-
}
71-
72250
73-
import * as d3 from 'd3';
74-
75-
export default {
76-
name: "Linked-List",
77-
data() {
78-
return {
79-
linkedList: undefined,
80-
result: "",
81-
showSuccessResult: false,
82-
showFailureResult: false,
83-
xAxis: 20,
84-
arrowXAxis: 0,
85-
circleRadius: 5,
86-
elements: [],
87-
circleContainer: undefined,
88-
showInputForm: false,
89-
showSearchForm: false,
90-
showDeleteForm: false,
91-
targetValue: null,
92-
insertedValue: null,
251+
console.log(cx, currentCircleXAxis, x, currentTextX);
252+
node.element.circle.transition()
253+
.duration(1000)
254+
.attr('cx', cx);
255+
256+
node.element.text.transition()
257+
.duration(1000)
258+
.attr('x', x);
259+
if (node.element.arrow) {
260+
console.log("arrowx:", nextArrow, arrowX);
261+
node.element.arrow.attr('transform', `translate(${arrowX}, 0)`);
262+
console.log(parseFloat(node.element.arrow.attr('transform').replace(/[^\d.-]/g, '')));
263+
}
264+
this.deleteNode(node.next, currentCircleXAxis, currentTextX, nextArrow)
265+
}
266+
267+
},
268+
269+
removeItemFromLinkedList() {
270+
let current = this.linkedList.head;
271+
let prev = current;
272+
while (current) {
273+
274+
if (current.data === this.targetValue) {
275+
const currentCircleXAxis = parseFloat(current.element.circle.attr('cx'));
276+
const currentTextX = parseFloat(current.element.text.attr('x'));
277+
let currentArrowX;
278+
if (current.element.arrow) {
279+
currentArrowX = parseFloat(current.element.arrow.attr('transform').replace(/[^\d.-]/g, '')) / 10;
280+
} else if (prev) {
281+
prev.element.arrow.remove();
282+
}
283+
current.element.circle.remove();
284+
current.element.text.remove();
285+
if (current.next) {
286+
current.data = current.next.data;
287+
288+
if (current.element.arrow) {
289+
current.element.arrow.remove()
93290
}
94-
},
95-
96-
methods: {
97-
createContainer() {
98-
this.circleContainer = d3.select(this.$refs.circleContainer)
99-
.append('svg')
100-
.attr('width', 500)
101-
.attr('height', 200);
102-
},
103-
104-
change() {
105-
for (const element of this.elements) {
106-
element.circle.transition()
107-
.duration(1000) // Animation duration in milliseconds
108-
.attr('fill', 'rgba(0, 255, 0, 0.8)');
109-
}
110-
},
111-
112-
toggleInsertForm() {
113-
this.showSuccessResult = false;
114-
this.showFailureResult = false;
115-
this.showInputForm = !this.showInputForm;
116-
this.hideDeleteForm();
117-
this.hideSearchForm();
118-
},
119-
120-
toggleSearchForm() {
121-
this.showSuccessResult = false;
122-
this.showFailureResult = false;
123-
this.showSearchForm = !this.showSearchForm;
124-
this.hideDeleteForm();
125-
this.hideInsertForm();
126-
},
127-
128-
toggleDeleteForm() {
129-
this.showSuccessResult = false;
130-
this.showFailureResult = false;
131-
this.hideInsertForm();
132-
this.hideSearchForm();
133-
this.showDeleteForm = !this.showDeleteForm;
134-
},
135-
136-
hideDeleteForm(){
137-
this.showDeleteForm = false;
138-
},
139-
hideInsertForm(){
140-
this.showInputForm = false;
141-
},
142-
hideSearchForm(){
143-
this.showSearchForm = false;
144-
},
145-
146-
insertFormSubmitAction() {
147-
if (this.insertedValue > 0) {
148-
149-
this.appendIntoLinkedList(this.insertedValue);
150-
this.showInputForm = false;
151-
this.insertedValue = null;
152-
} else {
153-
console.error("You've added negative number");
154-
}
155-
},
156-
157-
createCircle(num, createArrow) {
158-
159-
const finalRadius = 20;
160-
161-
const circle = this.circleContainer.append('circle')
162-
.attr('cx', this.xAxis)
163-
.attr('cy', 100)
164-
.attr('r', this.circleRadius)
165-
.attr('fill', 'rgba(0, 0, 255, 0.5)')
166-
.attr('opacity', .5);
167-
circle.transition()
168-
.duration(1000) // Animation duration in milliseconds
169-
.attr('r', finalRadius);
170-
171-
const text = this.circleContainer.append('text')
172-
.attr('x', this.xAxis)
173-
.attr('y', 100)
174-
.attr('dy', '.4em') // Vertical alignment adjustment
175-
.attr('text-anchor', 'middle') // Horizontal alignment
176-
.text(num);
177-
if (createArrow) {
178-
this.createArrow(this.xAxis + 70);
179-
}
180-
this.elements.push({circle: circle, text: text});
181-
182-
this.xAxis += this.circleRadius * 20;
183-
184-
return {circle: circle, text: text};
185-
186-
// this.circleContainer.append('circle')
187-
// .attr('cx', 90)
188-
// .attr('cy', 100)
189-
// .attr('r', finalRadius)
190-
// .attr('fill', 'red');
191-
//
192-
//
193-
},
194-
195-
createArrow(arrowX) {
196-
const arrowLength = 20;
197-
const arrowY = 100;
198-
// Line 1: Horizontal line
199-
const line1 = this.circleContainer.append('line')
200-
.attr('x1', arrowX - arrowLength - 20)
201-
.attr('y1', arrowY)
202-
.attr('x2', arrowX)
203-
.attr('y2', arrowY)
204-
.attr('stroke', 'black')
205-
.attr('stroke-width', 2);
206-
207-
// Line 2: Diagonal line (left)
208-
const line2 = this.circleContainer.append('line')
209-
.attr('x1', arrowX - 10)
210-
.attr('y1', arrowY - 5)
211-
.attr('x2', arrowX - arrowLength + 20)
212-
.attr('y2', arrowY)
213-
.attr('stroke', 'black')
214-
.attr('stroke-width', 2);
215-
216-
// Line 3: Diagonal line (right)
217-
const line3 = this.circleContainer.append('line')
218-
.attr('x1', arrowX - 10)
219-
.attr('y1', arrowY + 5)
220-
.attr('x2', arrowX - arrowLength + 20)
221-
.attr('y2', arrowY)
222-
.attr('stroke', 'black')
223-
.attr('stroke-width', 2);
224-
225-
return [line1, line2, line3];
226-
},
227-
228-
appendIntoLinkedList(num, pos) {
229-
if (!pos) {
230-
const circle = this.createCircle(num);
231-
let line;
232-
if (this.linkedList.head) {
233-
line = this.createArrow((this.xAxis - this.circleRadius * 40) + 70);
234-
}
235-
236-
this.linkedList.append(num, {circle: circle, lines: line});
237-
}
238-
},
239-
240-
241-
deleteNode(node, cx, x){
242-
if(node){
243-
const currentCircleXAxis = parseFloat(node.element.circle.attr('cx'));
244-
const currentTextX = parseFloat(node.element.text.attr('x'));
245-
console.log(cx, currentCircleXAxis, x, currentTextX);
246-
node.element.circle.transition()
247-
.duration(1000)
248-
.attr('cx', cx);
249-
250-
node.element.text.transition()
251-
.duration(1000)
252-
.attr('x', x);
253-
if(node.element.lines){
254-
for(const line of node.element.lines){
255-
line.attr('x1', currentTextX);
256-
}
257-
}
258-
this.deleteNode(node.next, currentCircleXAxis, currentTextX)
259-
}
260-
261-
return;
262-
263-
},
264-
265-
removeItemFromLinkedList() {
266-
let current = this.linkedList.head;
267-
268-
while (current) {
269-
if (current.data == this.targetValue) {
270-
const currentCircleXAxis = parseFloat(current.element.circle.attr('cx'));
271-
const currentTextX = parseFloat(current.element.text.attr('x'));
272-
console.log("Item found to delete");
273-
current.element.circle.remove();
274-
current.element.text.remove();
275-
if(current.next) {
276-
current.data = current.next.data;
277-
278-
for (const line of current.element.lines) {
279-
line.remove();
280-
}
281-
current.element = current.next.element;
282-
this.deleteNode(current.next, currentCircleXAxis, currentTextX);
283-
}
284-
break;
285-
}
286-
current = current.next;
287-
}
288-
this.targetValue = null;
289-
},
290-
291-
async searchIntoLinkedList() {
292-
this.showSuccessResult = false;
293-
this.showFailureResult = false;
294-
if (this.targetValue > 0) {
295-
this.showSearchForm = false;
296-
let current = this.linkedList.head;
297-
let found;
298-
let pos = 1;
299-
while (current) {
300-
found = current.data == this.targetValue;
301-
current.element.circle.transition()
302-
.duration(500).attr('fill', "pink");
303-
await new Promise(resolve => setTimeout(resolve, 600));
304-
if (found) {
305-
current.element.circle.transition()
306-
.duration(1000).attr('fill', "green");
307-
break;
308-
}
309-
await new Promise(resolve => setTimeout(resolve, 600));
310-
if (current.next) {
311-
for (const line of current.element.lines) {
312-
line.transition().duration(300).attr('stroke', "pink");
313-
}
314-
await new Promise(resolve => setTimeout(resolve, 300));
315-
}
316-
current = current.next;
317-
pos++;
318-
}
319-
if (found) {
320-
this.result = pos;
321-
this.showSuccessResult = true;
322-
console.log("target found");
323-
} else {
324-
this.showFailureResult = true;
325-
}
326-
this.targetValue = null;
327-
}
328-
},
329-
330-
generateLinkedList(nums) {
331-
for (const n of nums) {
332-
this.appendIntoLinkedList(n);
333-
}
291+
current.element = current.next.element;
292+
this.deleteNode(current.next, currentCircleXAxis, currentTextX, currentArrowX);
293+
}
294+
this.xAxis -= this.circleRadius * 20;
295+
break;
296+
}
297+
prev = current;
298+
current = current.next;
299+
}
300+
this.targetValue = null;
301+
},
302+
303+
async searchIntoLinkedList() {
304+
this.showSuccessResult = false;
305+
this.showFailureResult = false;
306+
if (this.targetValue > 0) {
307+
this.showSearchForm = false;
308+
let current = this.linkedList.head;
309+
let found;
310+
let pos = 1;
311+
while (current) {
312+
found = current.data === this.targetValue;
313+
current.element.circle.transition()
314+
.duration(500).attr('fill', "pink");
315+
await new Promise(resolve => setTimeout(resolve, 600));
316+
if (found) {
317+
current.element.circle.transition()
318+
.duration(1000).attr('fill', "green");
319+
break;
320+
}
321+
await new Promise(resolve => setTimeout(resolve, 600));
322+
if (current.next) {
323+
if (current.element.arrow) {
324+
current.element.arrow.selectAll('line').transition().duration(300).attr('stroke', "pink");
334325
}
335-
},
336-
mounted() {
337-
this.createContainer();
338-
this.linkedList = new LinkedList();
339-
this.generateLinkedList([1, 2, 3])
340-
},
326+
await new Promise(resolve => setTimeout(resolve, 300));
327+
}
328+
current = current.next;
329+
pos++;
330+
}
331+
if (found) {
332+
this.result = pos;
333+
this.showSuccessResult = true;
334+
console.log("target found");
335+
} else {
336+
this.showFailureResult = true;
337+
}
338+
this.targetValue = null;
339+
}
340+
},
341+
342+
generateLinkedList(nums) {
343+
for (const n of nums) {
344+
this.appendIntoLinkedList(n);
345+
}
341346
}
347+
},
348+
mounted() {
349+
this.createContainer();
350+
this.linkedList = new LinkedList();
351+
this.generateLinkedList([1, 2, 3])
352+
},
353+
}
342354
</script>
343355

344356
<style scoped>
345-
.success-message {
346-
background-color: #4caf50;
347-
color: white;
348-
padding: 10px;
349-
border-radius: 5px;
350-
margin-top: 10px;
351-
}
352-
353-
.fail-message {
354-
background-color: #af3e2e;
355-
color: white;
356-
padding: 10px;
357-
border-radius: 5px;
358-
margin-top: 10px;
359-
}
360-
361-
button {
362-
background-color: #3c3f41;
363-
color: white;
364-
border: none;
365-
padding: 10px 20px;
366-
margin: 5px;
367-
border-radius: 5px;
368-
cursor: pointer;
369-
}
370-
371-
input {
372-
padding: 10px;
373-
border: 1px solid #ccc;
374-
border-radius: 5px;
375-
}
357+
.success-message {
358+
background-color: #4caf50;
359+
color: white;
360+
padding: 10px;
361+
border-radius: 5px;
362+
margin-top: 10px;
363+
}
364+
365+
.fail-message {
366+
background-color: #af3e2e;
367+
color: white;
368+
padding: 10px;
369+
border-radius: 5px;
370+
margin-top: 10px;
371+
}
372+
373+
button {
374+
background-color: #3c3f41;
375+
color: white;
376+
border: none;
377+
padding: 10px 20px;
378+
margin: 5px;
379+
border-radius: 5px;
380+
cursor: pointer;
381+
}
382+
383+
input {
384+
padding: 10px;
385+
border: 1px solid #ccc;
386+
border-radius: 5px;
387+
}
376388
</style>

0 commit comments

Comments
 (0)
Please sign in to comment.