Link tables, queues, and stacks are some of the most basic data structures, and link tables are the most basic. Most of the complex data structures that follow evolved from them.
Linked list
A threaded data structure that differs from an array in that it is not necessarily stored sequentially in memory space. To ensure the continuity of elements in a linked list, a pointer is generally used to find the next element.
To implement a linked list of tables using java, you first need to define a node
1 2 3 4 5 6 7 8
classNode<T> { T value; Node<T> next;
publicNode(T value) { this.value = value; } }
Therefore, for a linked list, if you want to find an element based on the index, you can only start from the beginning with time complexity O(N).
If a predecessor node is added to the Node, then it becomes a bi-directional linked list.
The LinkedList in Java is a typical two-way linked list.
If you combine HashMap(Set) on LinkedList, it is LinkedHashMap(Set), which ensures the orderliness of the elements and allows O1 to get the elements.
A simple implementation of a linked list is as follows
// Singly linked list // The head node does not store elements // Need to record the head node, content is null; record the length of the list publicclassLinkList<T> implementsIterable<T>{ private Node head; // head node privateint N; // length of the list publicclassNode<T> { T item; // store element Node next; // point to the next node, a Node object publicNode(T item, Node next){ // constructor with arguments this.item = item; this.next = next; } } publicLinkList(){ // constructor with no arguments this.head = newNode(null,null); this.N = 0; } publicvoidclear(){ // clear the list: head node does not point to the next element N=0; head.next = null; } publicbooleanisEmpty(){ // check if the list is empty return N==0; } publicintlength(){ // get the length of the list return N; } public T get(int i){ // get the i-th element // Use loop, traverse from the head node, find i times Noden= head.next; for (intindex=0;index <i;index++){ n = n.next; // loop to point to the next node } return (T) n.item; } publicvoidinsert(T t){ // insert data // adding elements only requires the last node to point to the new node Noden= head; while(n.next!=null){ n = n.next; // tail node cannot be null } NodenewNode=newNode(t,null); n.next =newNode; N++; } publicvoidinsert(int i,T t){ // insert data before i // find the node before i Nodepre= head; for (intindex=0;index<=i-1;index++){ // because the head node actually loops i-1 times pre = pre.next; } // find the i node Nodecurr= pre.next; // create a new node and point to i NodenewNode=newNode(t,curr); // node before i points to the new node pre.next = newNode; // increment by 1 N++; } public T remove(int i){ // remove the i-th element and return it // get the node before i Nodepre= head; for (intindex=0;index<=i-1;index++){ pre = pre.next; } // find i Nodecurr= pre.next; // find the node after i Nodefur= curr.next; // connect the two and decrement by 1 pre.next = fur; N--; return (T) curr.item;
} publicintindexOf(T t){ // return the first occurrence of the element // start iterating from the head node, find every node's element, take out item and compare with T Noden= head; for (inti=0;n.next!=null;i++){ // keep finding as long as the next element is not null n = n.next; if (n.item.equals(t)){ return i; } // no alert has been set for elements that do not exist } return -1; } publicvoidreverse(){ //Flipping single linked list; Recursive flipping if (isEmpty()){ return; } else{ reverse(head.next); } } public Node reverse(Node curr){ //flip the single-linked cur, and return if(curr.next==null){ head.next = curr; return curr; } //recursively reverse the next node of the current node Nodeper= reverse(curr.next); // the new node is the next node after the flip per.next = curr; //the next node of the new node is the previous node before reversal curr.next = null; //this node is set as the tail node return curr; //not the last node then recursively flip the node before the last node }
Translated with www.DeepL.com/Translator (free version)
@Override public Iterator iterator() {
returnnewLIterator(); } privateclassLIteratorimplementsIterator { private node n; publicLIterator(){ this.n = head; //// initialize } @Override publicbooleanhasNext() { //execute next continuously if the hasNext condition is met return n.next!=null; }
@Override public Object next() { n = n.next; return n.item; } } }
Algorithm problems, the linked table often appear, the more basic types of questions include: the flip of the chain table, ring judgment, ring entry, multi-linked table to find the Kth big/smallest element, etc.. The linked table is also the basis for implementing jump tables.
Queue/Stack
Chained tables and queues are essentially a special type of single-linked table, differing in that they restrict the order of insertion/deletion of elements.
Queues:
For a queue, elements enter from one end and exit from the other, that is, the elements that enter first are deleted first, called in English: First In, First Out, abbreviated FIFO.
The more classical use of queues is in breadth-first search (hierarchical traversal of trees is actually also breadth-first search). In addition, queues can also have order, called priority queues, which have been implemented in java and are called PriorityQueue.
// FIFO Compared to a stack, one end of a queue goes in and one end goes out. publicclassQueue<T> implementsIterable<T> { privateclassNode<T>{ public T item; public Node next; publicNode(T item,Node next){ this.item = item; this.next = next; } } private Node head; //head privateint N; private Node last; //tail publicQueue(){ this.head = newNode(null,null); this.last = null; this.N = 0; } publicbooleanisEmpty(){ return N==0; } publicintsize(){ return N; } publicvoidenqueue(T t){ //Insert the chain from tail, in order from the first node if (last == null){ last= newNode(t,null); head.next = last; } else{ Nodeoldlast= last; last = newNode(t,null); oldlast.next = last; } N++; } public T dequeue(){ if (isEmpty()){ returnnull; //Header node start deletion } NodeoldeFirst= head.next; head.next = oldeFirst.next; N--; //The delete queue is deleting elements, so it needs to be reset last if (isEmpty()){ last = null; } return (T)oldeFirst.item; } @Override public Iterator<T> iterator(){ returnnewQIterator(); } privateclassQIteratorimplementsIterator{ private Node n; publicQIterator(){ this.n = head; } @Override publicbooleanhasNext() { return n.next!=null; }
@Override public Object next() { n = n.next; return (T)n.item; } } }
stacks:
The stack is the opposite, elements from one end into, to be from one end out. That is, first in, last out, called in English: First In, Last Out, or FILO.
Stacks are often used in algorithms, such as bracket punctuation matching problems, monotone stack problems, etc. Recursion is also a special use of stacks.
privateclassNode<T>{ public T item; public Node next; publicNode(T item,Node next){ this.item =item; this.next = next; } } privateint N; //Number of stack elements private Node head; publicStack(){ this.N = N; this.head = newNode(null,null); } publicbooleanisEmpty(){ return N==0; } publicintsize(){ return N; } //insert publicvoidpush(T t){ //Find the first node pointed to by the first node NodeoldNode= head.next; //create new node NodenewNode=newNode(t,null); //The first node points to the new node head.next = newNode; //The new node points to the original first node newNode.next = oldNode; N++; } public T pop(){ //The head node points to the first node NodeoldFirst= head.next; //head.next = oldFirst.next is not safe and needs to be verified if (oldFirst==null){ returnnull; } head.next = oldFirst.next; N--; return (T)oldFirst.item; } @Override public Iterator<T> iterator() { returnnewLIterator(); } privateclassLIteratorimplementsIterator{ private Node n; publicLIterator(){ this.n = head; } @Override publicbooleanhasNext() { return n.next!=null; } @Override public Object next() { n = n.next; return n.item; } }