Learning notes - circular linked list (expressed in C + +)

Students in school, please criticize and correct the deficiencies or errors in the narration.

Disadvantages of one-way linked list

We have learned the one-way linked list before, because the continuity does not need to be guaranteed during storage. Each node stores direct successors. We can easily insert and delete and expand the space. But we also found a disadvantage, that is, every time we operate on the list, we need to traverse from beginning to end or reach a node in the linked list, that is, the unity of direction.
At this time, we propose a method: set the tail node in the single linked list to node_ The next node attribute nextnode of end points to the head of the head node table. In this way, the linked list can form a loop, and the traversal can be completed no matter where it starts.

Node template definition of circular linked list

The node definition of circular linked list is the same as that of unidirectional linked list. We can find that the only difference between circular linked list and unidirectional linked list is the processing of tail nodes.

template <class T>
class Node {
protected:
	T data;
	Node<T>* nextnode;
public:
	Node();//Used to create an empty node
	Node(const T& obj);//Create data only nodes
	Node(const T& obj, Node<T>* address);//Create known nodes
	Node(const Node<T>& node);//Replication node


	virtual Node<T>* getNextNode();//Return next node address
	virtual void setNextNode(Node<T>* const address);//Set next node
	virtual T& showData();//Return data

	~Node();//Destroy node
};

Definition of circular linked list template

In the circular linked list, we directly introduce the same definition as the one-way linked list. Because the circular linked list is a deformation of the one-way linked list.

template<class T> class CircularList {
protected:
	Node<T>* head;//Chain header
	int LENGTH;//Linked list size

public:
	CircularList(); 	//Constructor to construct an empty table

public:
	virtual void add(const T& obj); 	//Add an element to the table
	virtual void insert(const T& obj, int index); 	//Insert an element into the table
	virtual T& check(int index)const; 	//View an element
	virtual bool remove(int index); 	//Delete an element
	virtual int length()const; 	//Return table length

public:
	virtual ~LinkList();
};

Implementation of circular linked list

Implementation of constructor

The constructor is similar to the one-way linked list. In the specific implementation, you need to instantiate a head node, and then set the next node of the head node to point to the head to realize the empty table definition of a circular linked list. What is a head node and why a head node should be used? For details, please refer to the notes of the one-way linked list (hyperlink: Single linked list).

template<class T>
CircularList<T>::CircularList() {
	head = new Node<T>(); 	//Set header node
	head->setNextNode(head);  	//Set the head node to point to the head node to form a circular linked list and an empty list
	LENGTH = 0;  	//Set the table length to 0
}

Add element to table

We should note that because the next node at the end of the list points to the head, the way we judge whether to reach the end of the linked list will change.

template<class T>
void CircularList<T>::add(const T& dt) {
	Node<T>* temp = new Node<T>(dt, head); 	//Create a new node. The new node is connected to the end of the linked list, so the next node points to the head
	if(temp == nullptr) { return; } 	//Failed to create node, return
	Node<T>* node = head->getNextNode(); 	//Get the next node of head
	while(node->getNextNode() != head) {
		node = node->getNextNode(); 
	}
	node->setNextNode(temp); 	//Connect the new node into the circular linked list
	LENGTH++; 
	return; 
}

Find elements in a linked list

We also start from the beginning and traverse from the beginning to the end of the linked list.

template<class T>
T& CircularList<T>::check(int index) {
	index--; 	//Incoming is a natural sort, convert it to start from 0
	if(index < 0 || index >= LENGTH) { throw "ERROR OBJ"; }
	Node<T>* node = head->getNextNode(); 	//Get next node
	for(int i = 1; i <= index; i++) {
		node = node->getNextNode(); 
	}
	return node->showData(); 
}

Insert an element into the linked list

Insert element is the same as one-way linked list. Find the insertion point and insert. We know that if we know the back of the p node in the inserted linked list and know the address of p, we only need to execute:

insert_element->setNextNode(p->getNextNode()); 
p->setNextNode(insert_element); 

At this time, the time complexity of insert() method is of constant order.
When we only know the subscript to be inserted or the data sample of the insertion position, we need to traverse the elements of the array. At this time, the time complexity of the insert() method is linear.

template<class T>
void CircularList<T>::insert(int index, const T& dt) {
	Node<T>* node = head->getNextNode(); 	//Get the first data address
	for(int i = 1; i < index; i++) {
		node = node->getNextNode(); 
	}
	Node<T>* temp = new Node<T>(dt, node->getNextNode()); 	//Create a new node
	if(temp == nullptr) { return; }
	node->setNextNode(temp); 
	return; 
}

Delete an element from the linked list

Similar to the one-way linked list, traverse the linked list from the beginning, compare the examples or reach the given subscript, and delete the corresponding elements.

template<class T>
bool CircularList<T>::remove(int index) {
	index--; 
	if(index <0 || index >= LENGTH) {
		return false; 
	}
	Node<T>* node = head->getNextNode(); 
	for(int i = 1; i < index - 1; i++) { 	//Find the previous node at the deleted location
		node = node->getNextNOde(); 
	}
	node->setNextNode(node->getNextNode()->getNextNode()); 	//The successor of the deleted point is given to the precursor of the deleted point
	delete node->getNextNode(); 	//Delete corresponding node
	return true; 
}

Tags: C++ data structure linked list

Posted on Tue, 21 Sep 2021 17:20:45 -0400 by Judas