The leading doubly circular linked list of the linear list

content

1. The focus of this chapter

2. Introduction of leading bidirectional circular linked list

2.1 What is a headed doubly linked list?

 2.2 The two most commonly used linked list structures

3. Implementation of common interface for leading bidirectional circular linked list 

3.1 Structure Creation

Fourth, the realization of the interface summary

 Five, online oj training and detailed explanation


1. The focus of this chapter

  1. Introduction to Doubly Circular Linked List
  2. Implementation of common interface for leading doubly circular linked list
  3. Implement interface summary
  4. Online oj training and detailed explanation

2. Introduction of leading bidirectional circular linked list

2.1 What is a headed doubly linked list?

  • Take the lead : There is a head node of the sentinel bit, which is an invalid node and does not store any valid information, but it is convenient for us to insert and delete the head and tail without judging that the head node points to NULL, and also does not need to be changed. The head pointer points to, and there is no need to pass a secondary pointer. 
  • Bidirectional : Each structure has two pointers, respectively pointing to the previous structure and the next structure.
  • Loop : The pointer of the last structure no longer points to NULL, but to the first structure. (unidirectional)
  • The front pointer of the first structure points to the last structure, and the back pointer of the last structure points to the first structure (bidirectional).

diagram 

 2.2 The two most commonly used linked list structures

  • There are more headless, one-way and two-way, whether there are 8 kinds of structures combined circularly, but the longest one is the headless one-way non-circular linked list and the headed two-way circular linked list
  • Headless one-way acyclic linked list: The structure is simple, and it is generally not used to store data alone. In practice, it is more of a substructure of other data structures, such as hash buckets, graph adjacency lists, and so on. In addition, this structure appears a lot in the written test interview.
  •  Headed doubly circular linked list: The structure is the most complex and is generally used to store data separately. The linked list data structures used in practice are all leading doubly circular linked lists. In addition, although the structure of this structure is complex, it will be found that the structure will bring many advantages after using the code to implement it, but the implementation is simple, and we will know it after the code is implemented.

3. Implementation of common interface for leading bidirectional circular linked list 

3.1 Structure Creation

typedef int DataType;
typedef struct DListNode
{
	DataType data;
	DListNode* prev;
	DListNode* next;
}DListNode;

3.2 Initialization of the headed doubly circular linked list 

void DListInint(DListNode** pphead)
{
	*pphead = (DListNode*)malloc(sizeof(DListNode));
	(*pphead)->next = (*pphead);
	(*pphead)->prev = (*pphead);
}

 Or use the method that returns a node to initialize

DListNode* DListInit()
	{
		DListNode* phead = (DListNode*)malloc(sizeof(DListNode));
		phead->next = phead;
		phead->prev = phead;
		return phead;
	}

 3.3 Create a new node

DListNode* BuyDListNode(DataType x)
{
	DListNode* temp = (DListNode*)malloc(sizeof(DListNode));
	if (temp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	temp->prev = NULL;
	temp->next = NULL;
	temp->data = x;
	return temp;
}

  3.4 tail plug

void DListPushBack(DListNode* phead,DataType x)
{
	DListNode* newnode = BuyDListNode(x);
	DListNode* tail = phead->prev;
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}

   3.5 Printing the linked list

void DListNodePrint(DListNode* phead)
{
	DListNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

    3.6 header

void DListNodePushFront(DListNode* phead, DataType x)
{
	DListNode* next = phead->next;
	DListNode* newnode = BuyDListNode(x);
	next->prev = newnode;
	newnode->next = next;
	newnode->prev = phead;
	phead->next = newnode;
}

    3.7 Tail deletion

void DListNodePopBack(DListNode* phead)
{
	if (phead->next == phead)
	{
		return;
	}
	DListNode* tail = phead->prev;
	DListNode* prev = tail->prev;
	prev->next = phead;
	phead->prev = prev;
	free(tail);
	tail = NULL;
}

 3.8 Header deletion

void DListNodePopFront(DListNode* phead)
{
	if (phead->next == phead)
	{
		return;
	}
	DListNode* firstnode = phead->next;
	DListNode* secondnode = firstnode->next;
	secondnode->prev = phead;
	phead->next = secondnode;
	free(firstnode);
	firstnode = NULL;
}

  3.9 Find data (return the node address of data)

DListNode* DListNodeFind(DListNode* phead, DataType x)
{
	DListNode* firstnode = phead->next;
	while (firstnode != phead)
	{
		if (firstnode->data == x)
		{
			return firstnode;
		}
		firstnode = firstnode->next;
	}
	return NULL;
}

    3.10 Insert node before pos position

void DListNodeInsert(DListNode* pos, DataType x)
{
	DListNode* prev = pos->prev;
	DListNode* newnode = BuyDListNode(x);
	newnode->next = pos;
	newnode->prev = prev;
	prev->next = newnode;
	pos->prev = newnode;
}

3.11 Delete the node at the pos position

void DListNodeErase(DListNode* pos)
{
	DListNode* prev = pos->prev;
	DListNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
	free(pos);
	pos = NULL;
}

Fourth, the realization of the interface summary

  1. Multi-drawing : It can clearly show the process of change, which is conducive to the realization of programming.
  2. Little knowledge : head->next can represent both the member variables of the previous structure and the address of the latter structure. When head->next is used as an lvalue, it represents a member variable, and when it is used as an rvalue, it represents the address of the next structure. Understanding this is very important for linked lists.
  3. Practice : Practice brings true knowledge
  4. Leading doubly linked list : Compared with a singly linked list, it is simpler to implement, and there is no need to discuss the length of the linked list in the same way as a singly linked list. Although the structure is more complicated, it is simpler and more convenient to use.

 Five, online oj training and detailed explanation

5.1 The intermediate node of the linked list (force buckle)

Given a  head non-empty singly linked list whose head node is , return the middle node of the linked list.

If there are two intermediate nodes, return the second intermediate node.

Input: [1,2,3,4,5]
Output: Node 3 in this list (serialized form: [3,4,5])
returns a node value of 3. (The evaluation system's serialized representation of this node is [3,4,5]).
Note that we return an object ans of type ListNode such that:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, and ans.next.next.next = NULL.

Source: LeetCode

 Idea: Fast and slow pointers

Take two pointers, both of which initially point to head, one is a fast pointer (fast) and takes two steps at a time, and the other is a slow pointer (slow) that takes one step at a time, when the fast pointer satisfies fast==NULL (even number of nodes) or fast ->next==NULL (odd number of nodes), slow points to the intermediate node, just return slow.

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* fast=head;
    struct ListNode* slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    return slow;
}

Guess you like

Origin blog.csdn.net/m0_62171658/article/details/123315681