目录
一、打印链表
void SListPrint(SListNode* phead)//打印链表直到为空
{
SListNode* cur = phead;//使当前指针从头指针开始,遍历指针
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");//最后别忘了空指针
}
二、建立新节点函数
向内存申请空间,建立新节点,新节点为空,扩容失败退出,否则返回一个新指针
因为用的很多单独写一个函数
SListNode* BuySListNode(SLTDataType x)
{
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
else
{
newnode->data = x;
newnode->next = NULL;
}
return newnode;
}
三、尾插
void SListPushBack(SListNode** pphead, SLTDataType x)
{
assert(pphead);//断言pphead是否有效
SListNode* newnode = BuySListNode(x);//调取函数申请空间存储新节点
if (*pphead == NULL)//这一种要单拎出来,因为找节点找的是当前节点的上一个节点,而如果它本来就是头结点就没有上一个节点,需特殊讨论
{
*pphead = newnode;
}
else
{
// 找尾
SListNode* tail = *pphead;//使尾节点为头结点,然后遍历尾节点直到为空,此时使尾节点的下一个节点为要插入的新节点
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
四、头插
void SListPushFront(SListNode** pphead, SLTDataType x)
{
assert(pphead);//断言pphead是否有效
SListNode* newnode = BuySListNode(x);//调取函数申请空间存储新节点
newnode->next = *pphead;//使新节点的下一个为头结点
*pphead = newnode;//此时的头结点就为新结点了,头插成功,一定时刻记着头结点何为节点,函数完成后头结
//点一定是第一个,尾节点是最后一个
}
五、尾删
1、链表空
2、链表只有一个节点
3、链表有多个节点
void SListPopBack(SListNode** pphead)
{
assert(pphead); //断言pphead是否有效
// 也可以暴力检查为空的情况
//assert(*pphead != NULL);
if (*pphead == NULL) // 温柔检查,链表是否为空
{
return;
}
else if ((*pphead)->next == NULL)//只有一个节点为头结点,直接释放头结点,然后头结点置空
{
free(*pphead);
*pphead = NULL;
}
else //多个节点,使尾结点指向头结点遍历,
{
SListNode* tail = *pphead;
while (tail->next->next != NULL)//找到尾节点的前一个位置
{
tail = tail->next;//然后使尾节点指向尾节点的下一个地址,连接好链表
}
free(tail->next);//释放为节点
tail->next = NULL;//使尾节点的下一个节点置空
}
}
六、头删
1、链表为空
2、链表非空
void SListPopFront(SListNode** pphead)
{
assert(pphead);//断言pphead是否有效
if (*pphead == NULL)
{
return;
}
else//存储好头结点的下一个节点的地址,然后释放头结点,最后使得头结点为刚才储存的节点
{
SListNode* next
free(*pphead);
*pphead = next;
}
}
七、指定数删除
建立一个当前节点,遍历节点查找数,如果找到了返回节点,并使当前节点的下一个节点为当前节点,相当于删除了该节点,没找到返回空指针
SListNode* SListFind(SListNode* phead, SLTDataType x)
{
SListNode* cur = phead;
while (cur != NULL)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
八、在pos位置之前插入
1、pos是第一个节点
2、pos不是第一个节点
void SListInsert(SListNode** pphead, SListNode* pos, SLTDataType x)
{
assert(pphead);//断言pphead是否有效
assert(pos);//断言pos是否有效
if (pos == *pphead)//pos是头结点
{
SListPushFront(pphead, x);//调用函数头插
}
else //建立pos的前一个节点为prev,遍历节点,直到prev的后一个节点等于pos时,调用
//函数申请内存,使prev指向新节点,新节点的下一个节点为pos,连接了链表
{
SListNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
SListNode* newnode = BuySListNode(x);//调用函数申请内存
prev->next = newnode;
newnode->next = pos;
}
}
九、在pos之后插入
void SListInsertAfter(SListNode* pos, SLTDataType x)
{
assert(pos);//断言pphead是否有效
SListNode* newnode = BuySListNode(x); //调用函数申请内存为新节点
newnode->next = pos->next;
pos->next = newnode;
}
十、删除pos 位置
void SListErase(SListNode** pphead, SListNode* pos)
{
assert(pphead);//断言pphead是否有效
assert(pos);//断言pos是否有效
if (*pphead == pos)//只有一个节点,为头结点,调用头删函数
{
SListPopFront(pphead);
}
else//多个节点,建立pos的前一个节点为prev,遍历节点,直到prev的后一个节点等于pos时,,使prev指向prev的后一个节点,然后使其指向pos的下一个,跳过pos
{
SListNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);//释放节点
pos = NULL;//最后必须置空,避免野指针的出现
}
}
十一、删除pos位置后面的值
void SListEraseAfter(SListNode* pos)
{
assert(pos);//断言pos是否有效
SListNode* next = pos->next;//建立next节点,使其对于pos下一个节点
if (next)//如果pos下一个节点不为空,pos->next = next->next跳过了next(删除pos位置后面的值)
{
pos->next = next->next;
free(next);//释放节点
next = NULL;//最后必须置空,避免野指针的出现
}
}
十二、删除所有节点(清空)
void SListDestroy(SListNode** pphead)
{
assert(pphead);//断言pphead是否有效
SListNode* cur = *pphead;//建立当前指,使其为头指针
while (cur)
{
SListNode* next = cur->next;//遍历节点
free(cur);//释放cur
cur = next;
}
*pphead = NULL;//最后必须置空,避免野指针的出现
}