浅谈关于数据结构中单链表的一些常用操作

篇博客主要介绍C数据结构中的单链表有关的增删查改操作,并且介绍列表的快慢指针,链表的逆置和合并等用法不说废话 直接上代码

#pragma once

#include <stdio.h>

#include <stdlib.h>

#include <assert.h>

typedef int DateType;

typedef struct PlistNode

{

DateType _date;

struct PlistNode* _next;

} PlistNode;

PlistNode* GetNode(DateType x);

void Print(PlistNode* plist);  //打印函数

void PushBack(PlistNode** pplist, DateType x);  //尾插

void PopBack(PlistNode** pplist);  //尾删

void PushFront(PlistNode** pplist, DateType x);  //头插

void PopFront(PlistNode** pplist);  //头删

PlistNode* ListFind(PlistNode* plist, DateType x);  //在pos的前面进行插入

void ListInsertAfter(PlistNode** pos, DateType x);  //在一个链表的pos位后插入

void SListEraseAfter(PlistNode** pos);  //删除某个链表pos后的一个节点

PlistNode* middleNode(PlistNode** head);  //返回链表的中间节点(快慢指针实现)

PlistNode* reverseList1(PlistNode** head);  //逆转链表(改变指针方向)

PlistNode* reverseList2(PlistNode** head);  //逆转链表(头插法每一个原链表值插入新链表)

PlistNode* FindKNode(PlistNode** head, int k);  //返回该链表中倒数第k个结点(含第k个节点)后所有结点(快慢指针实现)

链表相关

#include "Slist.h"

void Print(PlistNode* plist)  //打印函数

{

PlistNode* cur = plist;

while (cur != NULL)

{

printf("%d\n", cur->_date);

cur = cur->_next;

}

printf("\n");

}

PlistNode* GetNode(DateType x)  //得到一个新的节点,并将要插入得值赋给该节点

{

PlistNode* NewNode = (PlistNode*)malloc(sizeof(PlistNode));

NewNode->_date = x;

NewNode->_next = NULL;

return NewNode;  //新节点的指针

}

void PushBack(PlistNode** plist, DateType x)  //尾插

{

PlistNode* NewNode = GetNode(x);

if (*plist == NULL)

*plist = NewNode;

else

{

PlistNode* tail = *plist;

while (tail->_next != NULL)

tail = tail->_next;

tail->_next = NewNode;

}

}

void PopBack(PlistNode** plist)  //尾删

{

if (*plist == NULL || (*plist)->_next == NULL)

{

free(*plist);

*plist = NULL;

}

else

{

PlistNode* cur = *plist;

PlistNode* prv = NULL;

while (cur->_next != NULL)

{

prv = cur;

cur = cur->_next;

}

free(cur);

cur = NULL;

prv->_next = NULL;

}

}

void PushFront(PlistNode** plist, DateType x)  //头插

{

PlistNode* NewNode = GetNode(x);

if (*plist == NULL)

*plist = NewNode;

else

{

NewNode->_next = *plist;

*plist = NewNode;

}

}

void PopFront(PlistNode** plist)  //头删

{

if (*plist == NULL)

return;

else if ((*plist)->_next == NULL)

{

free(*plist);

*plist = NULL;

}

else

{

PlistNode* cur = (*plist)->_next;

free(*plist);

*plist = cur;

}

}

PlistNode* ListFind(PlistNode* pslist, DateType x)  //查找函数

{

assert(pslist);

PlistNode* cur = pslist;

while (cur != NULL)

{

if (x == cur->_date)

return cur;

cur = cur->_next;

}

return NULL;

}

void ListInsertAfter(PlistNode** pos, DateType x)  //在一个链表的pos位后插入

{

PlistNode* cur = GetNode(x);

PlistNode* tmp = NULL;

tmp = (*pos)->_next;

(*pos)->_next = cur;

cur->_next = tmp;

}

void SListEraseAfter(PlistNode** pos)  //删除某个链表pos后的一个节点

{

PlistNode* tmp = NULL;

PlistNode* cur = NULL;

tmp = (*pos)->_next;

cur = tmp->_next;

(*pos)->_next = cur;

free(tmp);

tmp = NULL;

}

PlistNode* middleNode(PlistNode** head)  //返回链表的中间节点(快慢指针实现)

{

PlistNode* fast = *head;

PlistNode* slow = *head;

while (fast != NULL && fast->_next != NULL)

{

fast = fast->_next->_next;

slow = slow->_next;

}

return slow;

}

PlistNode* reverseList1(PlistNode** head)  //逆转链表(改变指针方向)

{

if ((*head == NULL) || ((*head)->_next == NULL))

return *head;

PlistNode* n1 = (*head);

PlistNode* n2 = (*head)->_next;

PlistNode* n3 = n2->_next;

n1->_next = NULL;

while (n2 != NULL)

{

n2->_next = n1;

n1 = n2;

n2 = n3;

if (n3 != NULL)  //判断是否逆置完成

n3 = n3->_next;

}

return n1;

}

PlistNode* reverseList2(PlistNode** head)  //逆转链表(头插法每一个原链表值插入新链表)

{

if ((*head) == NULL || (*head)->_next == NULL)

return (*head);

PlistNode* cur = *head;

PlistNode* newhead = GetNode(cur->_date);

PlistNode* tmp = NULL;

while (cur->_next != NULL)

{

cur = cur->_next;

tmp = GetNode(cur->_date);

tmp->_next = newhead;

newhead = tmp;

}

return newhead;

}

PlistNode* FindKNode(PlistNode** head, int k)  //返回该链表中倒数第k个结点(含第k个节点)后所有结点(快慢指针实现)

{

if ((*head) == NULL)  //排除空指针情况

return NULL;

PlistNode* fast = *head;

PlistNode* slow = *head;

while (k--)

{

if (fast == NULL)  //排除k大于链表总长度

return NULL;

fast = fast->_next;

}

while (fast != NULL)

{

fast = fast->_next;

slow = slow->_next;

}

return slow;

}

测试函数

#include "Slist.c"

void text()

{

PlistNode* head = NULL;

PlistNode* cur = NULL;

PlistNode* res1 = NULL;

PlistNode* res2 = NULL;

PlistNode* res3 = NULL;

PushBack(&head, 1);

PushBack(&head, 2);

PushBack(&head, 3);

PushBack(&head, 4);

PushBack(&head, 5);

Print(head);

PopBack(&head);

Print(head);

PushFront(&head, 0);

Print(head);

cur = ListFind(head, 4);

Print(cur);

ListInsertAfter(&cur, 100);

Print(head);

SListEraseAfter(&cur);

Print(head);

res1 = middleNode(&head);

printf("%d\n\n", res1->_date);  //输出数据中间节点

res1 = reverseList1(&head);

Print(res1);

res2 = reverseList2(&res1);  //head已为空,传head无效

Print(res2);

res3 = FindKNode(&res2, 3);

printf("%d\n\n", res3->_date);  //输出倒数第k个节点数据

Print(res3);  //输出倒数第k个节点后所有节点数据

}

int main()

{

text();

system("pause");

return 0;

}

以上浅薄理解,欢迎各位大佬指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值