The structure of two-way leading circular linked list is shown in the figure

# Definition of bidirectional circular linked list structure

```typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* prev;
struct ListNode* next;
}LTNode;
```

Note that the structure definition does not reflect whether the linked list has rings.

The interfaces to be implemented for the two-way leading circular linked list are:

2. Destroy
3. Print
4. Tail insertion
6. Tail deletion
8. lookup
9. Insert in the previous position of pos
10. Delete pos node

# Create linked list and initialize

Note that a header node (sentinel node) is created here, and no data is saved.

```LTNode* IistInit()
{

}
```

# Open up new nodes

```LTNode* BuyListNode(LTDataType x)
{
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;

return newnode;
}
```

Note that the loop end condition is cur=phead

```void ListPrint(LTNode* phead)
{
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}

```

# Bidirectional linked list tail insertion

The time complexity is O(1), which is more efficient than single linked list and the same as sequential list

```void ListPushBack(LTNode* phead, LTDataType x)
{
tail->next = newnode;
newnode->prev = tail;
}
```

# Bidirectional linked list tail deletion

```void ListPopBack(LTNode* phead)
{
LTNode* tailPrev = tail->prev;
free(tail);
}
```

```void ListPushFront(LTNode* phead, LTDataType x)
{
newnode->next = next;
next->prev = newnode;
}
```

The prerequisite for deletion is that the linked list is not empty

```void ListPopFront(LTNode* phead)
{
LTNode* nextNext = next->next;
free(next);
}
```

Node with return value of x

```LTNode* ListFind(LTNode* phead, LTDataType x)
{
{
if(cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
```

# Insert in the previous position of pos

The default pos is in the linked list

If it is not a two-way linked list, it cannot be implemented (but it can also be implemented without a header node)

```void ListInsert(LTNode* phead, LTDataType x)
{
assert(pos);
LTNode* posPrev = pos->prev;
posPrev->next = newnode;
newnode->prev = posPrev;
newnode->next = pos;
pos->prev = newnode;
}
```

# Delete pos node

Here, the default pos is in the linked list, and pos cannot be a sentinel node, so there are at least phead and pos in the linked list

```void ListErase(LTNode* pos)
{
assert(pos);
LTNode* posPrev = pos->prev;
LTNode* posNext = pos->next;
posPrev->next = posNext;
posNext->prev = posPrev;
free(pos);
}
```

Before free, you still need to record a node. The difference from the single linked list is that the loop end condition and the free sentinel node are required. Note that phead is not set to null, and the user needs to set phead to null outside the function. Similar to free.

```void LsitDestroy(LTNode* phead)
{
{
LTNode* next = cur->next;
free(cur);
cur = next;
}
}
```

# Reuse ListInsert to implement head and tail insertion

```void ListPushFront(LTNode* phead, LTDataType x)
{
}
```

Tail insertion

```void ListPushBack(LTNode* phead, LTDataType x)
{
}
```

# Implementation of header deletion and tail deletion by reusing LsitErase

Note that assertions need to be preserved.

```assert(phead->next != phead);
```

It is used to ensure that the linked list is not empty. Here, it is ensured that the pos passed to ListErase is not phead

```void ListPopFront(LTNode* phead)
{
}
```

Tail deletion

```void ListPopBack(LTNode* phead)
{