Linear table
Linear table is a very flexible data structure, its length can be increased or shortened according to the needs, that is to say, the data elements of linear table can not only be accessed, but also inserted and deleted
- Linear table interface code
interface List<T> { void destroyList(); boolean listEmpty(); void add(T dataElement); void traverse(); void delete(int location); void insert(T dataElement, int location); }
Sequence table
The sequential representation of linear table refers to the storage of data elements of linear table with a group of storage units with continuous addresses, which is characterized by the same physical order of logically adjacent elements
-
Using array as storage container
-
Implementation code
class SqList<T> implements List<T> { private final int MAX_SIZE = 100; private Object[] dataElements; private int length; public SqList() { // TODO Auto-generated constructor stub this.dataElements = new Object[MAX_SIZE]; //Generic T cannot be used as a modifier to create an array this.length = 0; } @Override public void destroyList() { // TODO Auto-generated method stub this.length = 0; } @Override public boolean listEmpty() { // TODO Auto-generated method stub if(this.length == 0) return true; else return false; } @Override public void add(T dataElement) { // TODO Auto-generated method stub this.dataElements[length++] = dataElement; } @Override public void traverse() { // TODO Auto-generated method stub for (int i = 0; i < this.length; i++) { System.out.print(dataElements[i] + " "); } System.out.println(); } @Override public void delete(int location) { // TODO Auto-generated method stub for(int i = location; i < length ; i++) { //To delete, move length location times dataElements[i-1] = dataElements[i]; } dataElements[--length] = null; //Error prone: dataElements[length--] = null } @Override public void insert(T dataElement,int location) { // TODO Auto-generated method stub for(int i = length; i >= location ; i--) { //Insert length location + 1 time dataElements[i] = dataElements[i - 1]; } dataElements[location-1] = dataElement; length++; } }
-
Code analysis
-
An array of type Object
Because it is impossible to apply for an array of generic T type, an array of Object type is used instead. When adding data, the elements of generic T are added to the array (automatically up conversion), and the extracted elements are mandatory type conversion class output of generic T type
-
Number of moves during insert and delete operations
-
insert
When inserting, it needs to move back from the specified location position (first from the end) to move (length location) + 1 time
-
delete
When deleting, move forward from the last bit of the specified location position, and move the length location times (length location + 1 time is OK)
-
-
Chain list
Each independent storage cell is called a node. Each node is connected with the front and rear nodes by reference to form a linked list
Single chain table
The references in each node point to the successor nodes of the current node in one direction
-
code implementation
class LinkList_BackUp<T> implements List<T> { //Creating linked list by interpolation private class Node{ //Node class private Node next; private T dataElement; public Node() { //Construct head node // TODO Auto-generated constructor stub this.next = null; //Next in node (connect next node) this.dataElement = null; } public Node(T dataElement) { //Construct tail node // TODO Auto-generated constructor stub this.next = null; this.dataElement = dataElement; } } private int size; //Number of nodes private Node headNode; private Node node; //Tail node public LinkList_BackUp(){ this.size = 0; this.headNode = new Node(); //Initialize build header node node = headNode; //Node start from the initial node and cascade the nodes step by step } @Override public void destroyList() { // TODO Auto-generated method stub headNode.next = null; node = headNode; //Reset node size = 0; //size reset } @Override public boolean listEmpty() { // TODO Auto-generated method stub if(size == 0) return true; else return false; } @Override public void add(T dataElement) { //Add a new node at the end // TODO Auto-generated method stub Node newNode = new Node(dataElement); //Temporary node //Determine whether the end node is deleted if(node == null) { node = headNode; //When the end node is deleted, the previous node of the node will point to null, so the node will be discarded. When the node needs to be added again, it is necessary to relocate to the end node while(node.next != null) { node = node.next; } } node.next = newNode; node = node.next; size++; } @Override public void traverse() { // TODO Auto-generated method stub Node tempNode = headNode.next; while(tempNode != null) { //Judge whether the node is empty System.out.print(tempNode.dataElement + " "); tempNode = tempNode.next; } System.out.println(); } @Override public void delete(int location) { // TODO Auto-generated method stub if(location > size) System.out.println("Cross border warning"); Node tempNode = headNode; //Temporary node as search node for(int i = 0; i < location - 1; i++) { //Find the previous node of the corresponding node tempNode = tempNode.next; } //Delete the corresponding node tempNode.next = tempNode.next.next; if(location == size)//Set node to null when the end node is deleted node = null; //Equivalent to releasing the space of abandoned end nodes (GC will recycle automatically after dereference) size--; } @Override public void insert(T dataElement, int location) { // TODO Auto-generated method stub Node newNode = new Node(dataElement); Node tempNode = headNode; //The temporary node is used as the search node for(int i = 0; i < location - 1; i++) { //Find the previous node of the node corresponding to the location tempNode = tempNode.next; } newNode.next = tempNode.next; //Connect the next of the new node to the node corresponding to localization tempNode.next = newNode; //Link the next of the previous node of the node corresponding to the location to the newNode size++; } }
-
Code analysis
-
Node inner class
The implementation class of each Node represents a Node, which includes data and references
-
How to deal with node nodes when adding elements again after deleting tail nodes
When adding elements, the node node moves backward to link the new node to the tail node, so the node is always at the tail node. When the tail node is to be deleted, because the one-way linked list is not traceable, the node node is not the actual tail node, so the tail node needs to be relocated when adding again
-
Location location when inserting and deleting nodes
When one-way nodes insert or delete, they need to find the previous node of the corresponding node to operate, and the bidirectional linked list is more flexible
-
Double linked list
There are two references in each node, which point to the predecessor node and successor node of the current node respectively
-
code implementation
class DuLinkList<T> implements List<T> { private class Node{ //Node class private Node prior; //Pointing to the precursor private Node next; //Point to successor private T dataElement; //Node elements of generics public Node() { //Construct head node // TODO Auto-generated constructor stub this.prior = this; //The front and back references in the header node point to themselves this.next = this; //Next in node (connect next node) this.dataElement = null; } public Node(T dataElement) { //Construct storage node // TODO Auto-generated constructor stub this.prior = null; this.next = null; this.dataElement = dataElement; } } private int size; //Number of nodes private Node headNode; //Head node private Node node; //Tail node public DuLinkList() { //Initializing double linked list // TODO Auto-generated constructor stub size = 0; headNode = new Node(); node = headNode;//Initial tail node is the head node } @Override public void destroyList() {//Reset double linked list // TODO Auto-generated method stub headNode.next = headNode; headNode.prior = headNode; node = headNode; size = 0; } @Override public boolean listEmpty() { // TODO Auto-generated method stub if(size == 0) return true; else return false; } @Override public void add(T dataElement) {//Add node // TODO Auto-generated method stub Node newNode = new Node(dataElement); node.next = newNode; //Add a new node to the end of the tail node headNode.prior = newNode; //The precursor node of the head node points to the new node, forming a cycle newNode.prior = node; //The precursor of the new node points to the tail node newNode.next = headNode;//The back drive of the new node points to the head node, forming a cycle node = node.next;//Take the newly added node as the tail node size++; } @Override public void traverse() { // TODO Auto-generated method stub Node tempNode = headNode.next; while(tempNode != headNode) { //When the current node is the head node, the loop ends System.out.print(tempNode.dataElement + " "); tempNode = tempNode.next; } System.out.println(); } @Override public void delete(int location) { // TODO Auto-generated method stub if(location > size) System.out.println("Cross border warning"); else { Node tempNode = headNode; for(int i = 0; i < location; i++) { //Find the node corresponding to the location location tempNode = tempNode.next; } //Delete the corresponding node tempNode.prior.next = tempNode.next; //The successor node of the previous node of the deleted node points to the next node of the deleted node tempNode.next.prior = tempNode.prior;//Point the predecessor node of the next node of the deleted node to the previous node of the deleted node if(location == size) node = node.prior; //When the end node is deleted, the end node is updated to the previous node of the node //This makes it convenient to add new nodes to the actual tail nodes next time size--; } } @Override public void insert(T dataElement, int location) { // TODO Auto-generated method stub Node newNode = new Node(dataElement); Node tempNode = headNode; //Temporary node as search node for(int i = 0; i < location; i++) { //Find the node corresponding to location tempNode = tempNode.next; } //Insert complete newNode.next = tempNode; //Point the successor node of the newly inserted node to the inserted node newNode.prior = tempNode.prior; //Point the predecessor node of the newly inserted node to the previous node of the inserted node tempNode.prior.next = newNode; //Points the successor node of the previous node to the new node tempNode.prior = newNode; //Point the predecessor node of the inserted node to the new node size++; } }
-
Code analysis
-
Head node of double linked list
Both the preceding and subsequent references of a bidirectional node point to itself
-
Adding double linked list
1. Add the new node to the end of the tail node 2. The precursor of the head node points to the new node 3. The precursor of the new node points to the tail node 4. The following reference of the new node points to the head node
-
Insertion of double linked list
1. Find the inserted node corresponding to location 2. Point the successor node of the newly inserted node to the inserted node 3. Point the precursor node of the new inserted node to the previous node of the inserted node 4. Point the successor node of the previous node to the new node 5. Point the precursor node of the inserted node to the new node
-
Deletion of double linked list
1. Find the node corresponding to location 2. Point the successor node of the previous node of the deleted node to the next node of the deleted node 3. Point the precursor node of the next node of the deleted node to the previous node of the deleted node
-
How to deal with the node problem of adding new elements after deleting the tail node of bidirectional linked list
The reason and processing method are the same as the one-way linked list, but the bidirectional linked list is more simple in processing. Because the bidirectional linked list can be traced back, when the deletion operation is judged to be the tail node, the node is reset to the precursor node of the node
-
summary
- swot
- The total capacity of the sequence table is fixed
- The sequential table is more efficient in locating and searching, and the efficiency is not poor when inserting and deleting a large number of elements
- The capacity of linked list is unlimited
- Insertion and deletion of linked list is more efficient than sequential list
- Fallibility
- How to deal with the node of adding new element after deleting the tail node
- On the order of the links of the nodes in the insertion of the double linked list
- The conversion of array defined by Object type instead of generic T type in order table