文章目录
一、单链表
单向不带头不循环链表的实现
结构定义
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
struct SListNode
{
SLTDataType data;
struct SLNode* next;
};
typedef struct SListNode SLTNode;
动态申请一个节点
// 动态申请一个节点
SLTNode* BuySListNode(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
exit(-1);
}
newnode->next = NULL;
newnode->data = x;
return newnode;
}
单链表打印
// 单链表打印
void SListPrint(SLTNode* phead)
{
while (phead)
{
printf("%d->", phead->data);
phead = phead->next;
}
printf("NULL\n");
}
单链表尾插
// 单链表尾插
void SListPushBack(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
//1.没有结点
//2.至少一个结点
SLTNode* newnode = BuySListNode(x);
if (*pphead == NULL)
{
//没有结点
*pphead = newnode;
}
else
{
//有结点,找尾
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
单链表头插
// 单链表的头插
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
//链表是否为空不影响头插
SLTNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
单链表尾删
// 单链表的尾删
void SListPopBack(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);//不能没有结点
//如果只有一个结点
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
//不止一个结点
SLTNode* prev = *pphead;//存放最后一个结点的前一个
SLTNode* tail = *pphead;//找尾
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
prev->next = NULL;
free(tail);
}
}
单链表头删
// 单链表头删
void SListPopFront(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);//不能没有结点
//有一个结点也相同
SLTNode* next = (*pphead)->next;
free(*pphead);
*pphead = next;
}
单链表查找
// 单链表查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
while (phead != NULL)
{
if (phead->data == x)
break;
phead = phead->next;
}
return phead;
}
在pos位置之前去插入一个节点
// 在pos位置之前去插入一个节点
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
assert(pphead && *pphead && pos);
SLTNode* newnode = BuySListNode(x);
if (*pphead == pos)
{
//只有一个结点,头插
newnode->next = *pphead;
*pphead = newnode;
}
else
{
SLTNode* prev = *pphead;//存放pos结点的前一个
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = newnode;
newnode->next = pos;
}
}
删除在pos位置节点
// 删除在pos位置节点
void SListErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead && *pphead && pos);
//只有一个结点
if (*pphead == pos)
{
SLTNode* next = (*pphead)->next;//存放pos结点的下一个
free(*pphead);
*pphead = next;
}
else
{
SLTNode* prev = *pphead;//存放pos结点的前一个
while (prev != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
//也可如下
//SLTNode* tail = *pphead;//找pos
//while (tail->next != NULL)
//{
// if (tail == pos)
// break;
// prev = tail;
// tail = tail->next;
//}
//prev->next = tail->next;
//free(tail);
}
}
单链表在pos位置之后插入x
// 单链表在pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* newnode = BuySListNode(x);
SLTNode* next = pos->next;
pos->next = newnode;
newnode->next = next;
}
单链表删除pos位置之后的值
// 单链表删除pos位置之后的值
void SListEraseAfter(SLTNode* pos)
{
assert(pos);
assert(pos->next);//pos后面不能没有
//链接删除结点左右两个结点
SLTNode* next = pos->next;
pos->next = next->next;
free(next);
}
单链表销毁
void SListDestory(SLTNode** pphead)
{
SLTNode* next = *pphead;
while (next != NULL)
{
SLTNode* temp = next;
next = next->next;
free(temp);
}
*pphead = NULL;
}
二、双向链表
双向带头循环链表的实现
结构定义
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//带头结点的双向循环链表
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* next;
struct ListNode* prev;
}LTNode;
初始化链表
//初始化链表
LTNode* ListInit()
{
//创建头结点
LTNode* head = (LTNode*)malloc(sizeof(LTNode));
if (head == NULL)
exit(-1);
head->next = head;
head->prev = head;
return head;
}
双向链表打印
// 双向链表打印
void ListPrint(LTNode* phead)
{
assert(phead);
LTNode* sur = phead->next;
while (sur != phead)
{
printf("%d->", sur->data);
sur = sur->next;
}
printf("NULL\n");
}
创建一个新的结点
//创建一个新的结点
LTNode* BuyListNode(LTDataType x)
{
//创建结点
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
if (newnode == NULL)
exit(-1);
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
双向链表尾插
// 双向链表尾插
void ListPushBack(LTNode* phead, LTDataType x)
{
LTNode* newnode = BuyListNode(x);
//直接链接,不用考虑多余情况
LTNode* tail = phead->prev;
tail->next = newnode;
newnode->prev = tail;
phead->prev = newnode;
newnode->next = phead;
}
双向链表尾删
// 双向链表尾删
void ListPopBack(LTNode* phead)
{
//头结点不为空,并且链表不为空
assert(phead && phead->next != phead);
LTNode* tail = phead->prev;
LTNode* tailPrev = tail->prev;//尾的前一个
tailPrev->next = phead;
phead->prev = tailPrev;
free(tail);
}
双向链表头插
// 双向链表头插
void ListPushFront(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* newnode = BuyListNode(x);
LTNode* first = phead->next;//第一个有效结点
phead->next = newnode;
newnode->next = first;
newnode->prev = phead;
first->prev = newnode;
}
双向链表头删
// 双向链表头删
void ListPopFront(LTNode* phead)
{
//头结点不为空,并且链表不为空
assert(phead && phead->next != phead);
LTNode* first = phead->next;
LTNode* firstNext = first->next;
phead->next = firstNext;
firstNext->prev = phead;
free(first);
}
双向链表查找
// 双向链表查找
LTNode* ListFind(LTNode* phead, LTDataType x)
{
assert(phead && phead->next != phead);
LTNode* temp = phead->next;
while (temp != phead)
{
if (temp->data == x)
return temp;
temp = temp->next;
}
//找不到
return NULL;
}
双向链表在pos的前面进行插入
// 双向链表在pos的前面进行插入
void ListInsert(LTNode* pos, LTDataType x)
{
assert(pos);
LTNode* newnode = BuyListNode(x);
LTNode* posPrev = pos->prev;
newnode->prev = posPrev;
posPrev->next = newnode;
newnode->next = pos;
pos->prev = newnode;
}
双向链表删除pos位置的节点
// 双向链表删除pos位置的节点
void ListErase(LTNode* pos)
{
assert(pos);
LTNode* posPrev = pos->prev;
posPrev->next = pos->next;
pos->next->prev = posPrev;
free(pos);
}
摧毁链表
// 摧毁链表
void ListDestroy(LTNode* phead)
{
assert(phead);
LTNode* sur = phead->next;
LTNode* next = NULL;
while (sur != phead)
{
next = sur->next;
free(sur);
sur = next;
}
free(phead);
}
为了更快捷的写出双向链表,可以仅靠ListErase和ListInsert来实现相关的插入删除操作。