Linear table (List): A finite sequence of zero or more data elements.A linear table is a sequence with a one-to-one relationship, not a one-to-many relationship.Linear tables require limitations and the same data type.
This paper mainly refers to the principle of telephone data structure to understand, and uses Javascript to implement related operations on linear tables.
Create a one-way chain table:
//Create Node class Node{ constructor(element){ this.element = element;//Data Domain this.next = undefined;//Pointer field } }; //To determine if the incoming object is equal to the elements of the chain table, use indexOf() later, write it here first function(a,b){ return a == b; }; //Create Chain List class LinkedList { constructor(equalsFn = defaultEquals) { this.equalsFn = equalsFn; this.count = 0; this.head = undefined; } };
Query operation
Determine if one-way table is empty
isEmpty() { return this.size() === 0; }
Calculating the Length of a One-way Chain List
size() { return this.count; }
Query the location of an element in a list of chains
indexOf(element) { let current = this.head; for (let i = 0; i < this.size() && current != null; i++) { if (this.equalsFn(element, current.element)) { return i; } current = current.next; } return -1; }
Get the first element
getHead() { return this.head; }
Get Element Action
getElementAt(index) { if (index >= 0 && index <= this.count) { let node = this.head; for (let i = 0; i < index && node != null; i++) { node = node.next; } return node; } return undefined; }
Insert operation
Tail interpolation
push(element) { const node = new Node(element); let current; if (this.head == null) { // catches null && undefined this.head = node; } else { current = this.head; while (current.next != null) { current = current.next; } current.next = node; } this.count++; }
Insert elements anywhere
insert(element, index) { if (index >= 0 && index <= this.count) { const node = new Node(element); if (index === 0) { const current = this.head; node.next = current; this.head = node; } else { const previous = this.getElementAt(index - 1); node.next = previous.next; previous.next = node; } this.count++; return true; } return false; }
Delete operation
Delete elements at specific locations
removeAt(index) { if (index >= 0 && index < this.count) { let current = this.head; if (index === 0) { this.head = current.next; } else { const previous = this.getElementAt(index - 1); current = previous.next; previous.next = current.next; } this.count--; return current.element; } return undefined; }
Delete an element of the list directly
remove(element) { const index = this.indexOf(element); return this.removeAt(index); }
Modify Action
One-way list converted to string
toString() { if (this.head == null) { return ''; } let objString = `${this.head.element}`; let current = this.head.next; for (let i = 1; i < this.size() && current != null; i++) { objString = `${objString},${current.element}`; current = current.next; } return objString; } }
Empty One-way Chain List
clear() { this.head = undefined; this.count = 0; }
These are the common operations for one-way chained lists.
Since a one-way chain table can only be traversed from beginning to end, if the query is for the next node, the one-way table time complexity is O(1), but if the query is for the previous node, then the time complexity is O(n).If the list can also be traversed in both directions, then the time complexity of the query operation is O(1), then our predecessors have proposed the bi-directional list of chains.Since the two-way chain table is an extension of the one-way chain table, but there is only one more pointer, which is not helpful for query operation, so the implementation method is the same as the one-way chain table, which is not discussed here.
Create a two-way chain table
//Create Node class DoublyNode extends Node { constructor(element, next, prev) { super(element, next);//inherit this.prev = prev;//Add Forward Pointer } }; //Initialize Bi-directional Chain List class DoublyLinkedList extends LinkedList { constructor(equalsFn = defaultEquals) { super(equalsFn); this.tail = undefined;//Reference to the last element of the list }
Insert operation
Tail interpolation
push(element) { const node = new DoublyNode(element); if (this.head == null) { this.head = node; this.tail = node; // NEW } else { // attach to the tail node // NEW this.tail.next = node; node.prev = this.tail; this.tail = node; } this.count++; }
Add elements anywhere
insert(element, index) { if (index >= 0 && index <= this.count) { const node = new DoublyNode(element); let current = this.head; if (index === 0) { if (this.head == null) { // NEW this.head = node; this.tail = node; // NEW } else { node.next = this.head; this.head.prev = node; // NEW this.head = node; } } else if (index === this.count) { // last item NEW current = this.tail; current.next = node; node.prev = current; this.tail = node; } else { const previous = this.getElementAt(index - 1); current = previous.next; node.next = current; previous.next = node; current.prev = node; // NEW node.prev = previous; // NEW } this.count++; return true; } return false; }
Delete operation
Delete elements at specific locations
removeAt(index) { if (index >= 0 && index < this.count) { let current = this.head; if (index === 0) { this.head = this.head.next; // if there is only one item, then we update tail as well //NEW if (this.count === 1) { // {2} this.tail = undefined; } else { this.head.prev = undefined; } } else if (index === this.count - 1) { // last item //NEW current = this.tail; this.tail = current.prev; this.tail.next = undefined; } else { current = this.getElementAt(index); const previous = current.prev; // link previous with current's next - skip it to remove previous.next = current.next; current.next.prev = previous; // NEW } this.count--; return current.element; } return undefined; }
Query operation
Location of query elements
indexOf(element) { let current = this.head; let index = 0; while (current != null) { if (this.equalsFn(element, current.element)) { return index; } index++; current = current.next; } return -1; }
Query tail element
getTail() { return this.tail; }
Modify Action
Empty Two-way Chain List
clear() { super.clear(); this.tail = undefined; }
Bidirectional Link Table Object to String
inverseToString() { if (this.tail == null) { return ''; } let objString = `${this.tail.element}`; let previous = this.tail.prev; while (previous != null) { objString = `${objString},${previous.element}`; previous = previous.prev; } return objString; } }