链表的结构体以及函数声明
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* prev;
struct ListNode* next;
}ListNode;
//初始化
//void ListInit();
ListNode* ListInit(ListNode* pHead);
// 创建返回链表的头结点.
ListNode* BuyListNode(LTDataType x);
// 双向链表销毁
void ListDestory(ListNode** ppHead);
//双向链表清除
void ListClear(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
//双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
//双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
//双向链表头删
void ListPopFront(ListNode* pHead);
//双向链表查找,是Insert和erase的基础
ListNode* ListFind(ListNode* pHead, LTDataType x);
//双向链表在pos位置之前插入节点
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
链表初始化
两种方式,一种是传二级指针这样就可以直接改变它,一种是利用返回值接收
//也可以写成void ListInit(ListNode* pHead),不过在测试的时候就要传进来二级指针。因为phead要发生改变
//这里写成ListNode* 测试的时候可以传入一级指针,满足接口一致性
ListNode* ListInit(ListNode* pHead)
{
/*ListNode* pHead = BuyListNode(0);*/
pHead->next = pHead;
pHead->prev = pHead;
return pHead;
}
创建节点
ListNode* BuyListNode(LTDataType x)
{
ListNode* node= (ListNode*)malloc(sizeof(ListNode));
node->next= NULL;
node->prev = NULL;
node->data = x;
return node;
}
查找节点
通过data来查找,如果有重复的返回第一个。这个接口可以和查找,删除进行配合
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
插入节点
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* posPrev = pos->prev;
ListNode* newNode = BuyListNode(x);
posPrev->next = newNode;
newNode->prev = posPrev;
newNode->next = pos;
pos->prev = newNode;
}
删除节点
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* posPrev = pos->prev;
ListNode* newNode = BuyListNode(x);
posPrev->next = newNode;
newNode->prev = posPrev;
newNode->next = pos;
pos->prev = newNode;
}
尾删尾插,头删头插
两种方法,一种是直接实现,一种是利用已有接口
//尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
//assert(pHead);
//ListNode* newNode = BuyListNode(x);
//ListNode* tail = pHead->prev;
//tail->next = newNode;
//newNode->prev = tail;
这里犯了一个错误,让newNode的prev指向了头
//pHead->prev = newNode;
//newNode->next = pHead;
//Insert代表在所选位置之前插入,这样ListInsert(pHead->prev, x);插入到倒数第二个去了
ListInsert(pHead, x);
}
//尾删
void ListPopBack(ListNode* pHead)
{
//assert(pHead);
//assert(pHead->next != pHead);
//ListNode* tail = pHead->prev;
//ListNode* tailPrev = tail->prev;
///*printf("%d %d", tail->data, tailPrev->data);*/
//tailPrev->next = pHead;
//pHead->prev = tailPrev;
//free(tail);
ListErase(pHead->prev);
}
//头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
/*assert(pHead);
ListNode* Next = pHead->next;
ListNode* newNode = BuyListNode(x);
pHead->next = newNode;
newNode->prev = pHead;
newNode->next = Next;
Next->prev = newNode;*/
ListInsert(pHead->next, x);
}
//头删
void ListPopFront(ListNode* pHead)
{
/*assert(pHead);
assert(pHead->next!=pHead);
ListNode* next = pHead->next;
ListNode* second =next->next;
pHead->next = second;
second->prev = pHead;
free(next);*/
ListErase(pHead->next);
}
完整代码链接:
双向带头循环链表的实现