目录
一、无头单向非循环链表
1.概念
无头单向非循环链表:结构简单,一般不会单独用来存储数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等。
2.实现
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
SListNode* BuySListNode(SLTDateType x)
{
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
if (newnode == NULL)
{
perror("malloc fall");
exit(-1);
}
//成功
newnode->data = x;
newnode->next = NULL;
return newnode;
}
// 单链表打印
void SListPrint(SListNode* phead);
void SListPrint(SListNode* phead)
{
SListNode* tail = phead;
while (tail != NULL)
{
printf("%d->", tail->data);
tail = tail->next;
}
printf("NULL\n");
}
// 单链表尾插
void SListPushBack(SListNode** pphead, SLTDateType x);
void SListPushBack(SListNode** pphead, SLTDateType x)
{
SListNode* tail = *pphead;
SListNode* newnode = BuySListNode(x);
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
// 单链表的头插
void SListPushFront(SListNode** pphead, SLTDateType x);
void SListPushFront(SListNode** pphead, SLTDateType x)
{
SListNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
// 单链表的尾删
void SListPopBack(SListNode** pphead);
void SListPopBack(SListNode** pphead)
{
assert(*pphead);
if ((*pphead)->next == NULL)
{
*pphead = NULL;
}
else
{
SListNode* tail = *pphead;
while (tail->next->next != NULL)
{
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
}
}
// 单链表头删
void SListPopFront(SListNode** pphead);
void SListPopFront(SListNode** pphead)
{
assert(*pphead);
if((*pphead)->next == NULL)
{
*pphead = NULL;
}
else
{
SListNode* tail = (*pphead)->next;
free(*pphead);
*pphead = tail;
}
}
// 单链表查找
SListNode* SListFind(SListNode* phead, SLTDateType x);
SListNode* SListFind(SListNode* phead, SLTDateType x)
{
SListNode* tail = phead;
while (tail)
{
if (tail->data == x)
{
return tail;
}
tail = tail->next;
}
return NULL;
}
// 分析思考为什么不在pos位置之前插入?
若在pos位之前插入需要遍历整个链表,时间复杂度为O(N);
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x);
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
assert(pos);
SListNode* newnode = BuySListNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
//在pos之前插入值
void SListInsert(SListNode** pphead, SListNode* pos, SLTDateType x);
void SListInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
{
assert(pos);
SListNode* prev = *pphead;
if (pos == *pphead)
{
SListPushFront(pphead,x);
}
else
{
while (prev->next != pos)
{
prev = prev->next;
}
SListNode* newnode = BuySListNode(x);
newnode->next = pos;
pos->next = newnode;
}
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);
void SListEraseAfter(SListNode* pos)
{
assert(pos);
assert(pos->next);
SListNode* tail = pos->next;
pos->next = tail->next;
free(tail);
}
//删除pos位置
void SListErase(SListNode** pphead, SListNode* pos);
void SListErase(SListNode** pphead, SListNode* pos)
{
assert(pos);
SListNode* tail = *pphead;
if (pos == *pphead)
{
SListPopFront(pphead);
}
else
{
while (tail->next != pos)
{
tail = tail->next;
}
tail->next = pos->next;
free(pos);
}
}
// 单链表的销毁
void SListDestroy(SListNode** pphead);
void SListDestroy(SListNode** pphead)
{
SListNode* tail = *pphead;
while (tail)
{
SListNode* next = tail->next;
free(tail);
tail = next;
}
*pphead = NULL;
}
二、带头双向循环链表
1.概念
带头双向循环链表:结构最复杂,一般用来单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现反而会很简单。
2.实现
typedef int LTDataType;
typedef struct ListNode
{
struct ListNode* next;
struct ListNode* prev;
LTDataType data;
}ListNode;
//malloc一个新的结点
ListNode* BuyListNode(LTDataType x)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
if (node == NULL)
{
perror("malloc fail");
exit(-1);
}
node->data = x;
node->next = NULL;
node->prev = NULL;
}
// 创建返回链表的头结点.
ListNode* ListInit();
ListNode* ListInit()
{
ListNode* head = BuyListNode(-1);
head->next = head;
head->prev = head;
return head;
}
// 双向链表销毁
void ListDestory(ListNode* phead);
void ListDestory(ListNode* phead)
{
assert(phead);
ListNode* tail = phead->next;
while (tail != phead)
{
ListNode* next = tail->next;
free(tail);
tail = next;
}
free(phead);
}
// 双向链表打印
void ListPrint(ListNode* phead);
void ListPrint(ListNode* phead)
{
assert(phead);
ListNode* tail = phead->next;
while (tail != phead)
{
printf("%d ", tail->data);
tail = tail->next;
}
printf("\n");
}
// 双向链表尾插
void ListPushBack(ListNode* phead, LTDataType x);
void ListPushBack(ListNode* phead, LTDataType x)
{
assert(phead);
/*ListNode* tail = phead->prev;
ListNode* newnode = BuyListNode(x);
tail->next = newnode;
newnode->prev = tail;
phead->prev = newnode;
newnode->next = phead;*/
ListInsert(phead, x);
}
// 双向链表尾删
void ListPopBack(ListNode* phead);
void ListPopBack(ListNode* phead)
{
assert(phead);
assert(phead->next != phead);
/*ListNode* tail = phead->prev;
ListNode* tailprev = tail->prev;
tailprev->next = phead;
phead->prev = tailprev;
free(tail);*/
ListErase(phead->prev);
}
// 双向链表头插
void ListPushFront(ListNode* phead, LTDataType x);
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);
void ListPopFront(ListNode* phead)
{
assert(phead);
assert(phead->next != phead);
/*ListNode* tail = phead->next;
ListNode* next = tail->next;
phead->next = next;
next->prev = phead;
free(tail);*/
ListErase(phead->next);
}
// 双向链表查找
ListNode* ListFind(ListNode* phead, LTDataType x);
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的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* newnode = BuyListNode(x);
ListNode* tail = pos->prev;
tail->next = newnode;
newnode->next = pos;
newnode->prev = tail;
pos->prev = newnode;
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prev = pos->prev;
ListNode* next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
}