链表
单向链表的缺陷
单链表的缺陷:1.查找的速度慢
2.不能从后往前找
3.找不到前驱
双链表的优势:把链表的删除和插入的时间复杂度从o(n)变成了o(1)
链表的结构
两两组合,一共有8种链表
带头双向循环链表的宏定义
typedef int LTDataType
typedef struct ListNode
{
struct ListNode* next;
struct ListNode* prve;
LTDataType data;
}ListNode;
带哨兵位的双向循环链表的结构虽然复杂了,但是可操作性增加了。
常用接口
//创建节点的接口
ListNode* BuyListNode(LTDataType x);
//初始化哨兵位节点
ListNode* ListInit();
//摧毁链表
void ListDestory(ListNode*phead);
//尾插
void ListPushBack(ListNode* phead,LTDataType x);
//头插接口(传入的指针是哨兵位指针)
void ListPushFront(ListNode* phead,LTDatatype x);
//尾删接口
void ListPopBack(ListNode* phead);
//头删接口
void ListPopFront(ListNode* phead);
//打印链表
void Listprint(ListNode* phead);
//查找接口并具有修改作用
ListNode* ListFind(ListNode* phead,LTDataType x);
/pos位置之前插入x
void ListInsert(ListNode*pos,LTDataType x);
//删除pos位置的值
void ListErase(ListNode* pos);
创建节点接口
ListNode* BuyListNode(LTDataType x)
{
ListNode* newnode=(ListNode*)malloc(sizeof(ListNode));
newnode->data=x;
newnode->next=NULL;
newnode->prve=NULL;
return newnode;
}
初始化哨兵位节点接口
ListNode* ListInit()
{
//哨兵位的节点
ListNode* phead=BuyListNode(0);
phead->next=phead;
phead->prve=phead;
return phead;
}
摧毁链表接口
void ListDestory(ListNode*phead)
{
assert(phead);
ListNode* cur=phead->next;
while(cur!=phead)
{
ListNode*next=cur->next;
free(cur);
cur=next;
}
free(phead);
phead=NULL;
}
尾插接口
void ListPushBack(ListNode* phead,LTDataType x)
{
//将原链表的最后一个单元的地址存储在指针变量tail中
ListNode*tail=phead->prev;
//创建新的链表单元
ListNode*newnode=BuyListNode(x);
tail->next=newnode;
newnode->prev=tail;
newnode->next=phead;
phead->prev=newnode;
}
头插接口
void ListPushFront(ListNode* phead,LTDatatype x)
{
assert(phead);
//如果为空链表,那么phead->next==phead;
ListNode* first=phead->next;
ListNode*newnode=BuyListNode(x);
phead->next=newnode;
newnode->next=first;
newnode->prev=phead;
first->prev=newnode;
}
尾删接口
void ListPopBack(ListNode* phead)
{
assert(phead);
ListNode* tail=phead->prev;
ListNode* prev=tail->prev;
phead->prev=prev;
prev->next=phead;
free(tail);
tail=NULL;
}
头删接口
void ListPopFront(ListNode* phead)
{
assert(phead);
assert(phead->next!=phead);
ListNode* first=phead->next;
ListNode*second=first->next;
phead->next=first->next;
second->prev=phead;
free(first);
first=NULL;
}
打印链表
void Listprint(ListNode* phead)
{
ListNode* cur=phead->next;
while(cur!=phead)
{
printf("%d",cur->data);
cur=cur->next;
}
free(cur);
cur=NULL;
}
查找接口
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;
}
pos位置之前插入x
void ListInsert(ListNode*pos,LTDataType x)
{
assert(pos);
ListNode*prev=pos->prev;
ListNode*newnode=BuyListNode(x);
prev->next=newnode;
newnode->prev=prev;
newnode->next=pos;
pos->prev=newnode;
}
删除pos位置的值
void ListErase(ListNode* pos)
{
assert(pos);
assert(pos!=phead);
ListNode*prev=pos->prev;
ListNode*next=pos->next;
prev->next=next;
next->prev=prev;
free(pos);
pos=NULL;
}