从零手写单向链表,增删查改一次性讲清

在这里插入图片描述
API:应用程序接口

  1. 创建链表
  2. 链表插入(头插、尾插)
  3. 链表删除(头删、尾删)
  4. 查找
  5. 修改
  6. 链表遍历
  7. 链表销毁

链表数据类型构造:

//链表结点类型
typedef struct node
{
int data; //数据域:保存的数据
struct node *pnext; //指针域:下一个结点的地址
}Node_t;

//链表对象类型

typedef struct link
{
Node_t *phead; //链表头节点指针
int clen; //链表当前结点的个数
}Link_t;

单向链表的创建

Link_t *create_link()
{
Link_t *plink = malloc(sizeof(Link_t));
if (NULL == plink)
{
printf("malloc error\n");
return NULL;
}
plink->phead = NULL;
plink->clen = 0;
return plink;
}

单向链表头插

  1. 创建结点
  2. 为结点赋值
  3. 让要插入结点的指针域指向原来的头节点
  4. 让phead指向新插入结点

在这里插入图片描述

int insert_link_head(Link_t *plink, int data)
{
Node_t *pinsert = malloc(sizeof(Node_t));
if (NULL == pinsert)
{
	printf("malloc error\n");
	return -1;
}
pinsert->data = data;
pinsert->pnext = NULL;
pinsert->pnext = plink->phead;
plink->phead = pinsert;
plink->clen++;
return 0;
}

单向链表尾插
在这里插入图片描述

int insert_link_tail(Link_t *plink, int data)
{
Node_t *pinsert = malloc(sizeof(Node_t));
if (NULL == pinsert)
{
printf("mallocc error\n");
return -1;
}
pinsert->data = data;
pinsert->pnext = NULL;
if (is_empty_link(plink))
{
plink->phead = pinsert;
}
else
{
Node_t *ptmp = plink->phead;
while (ptmp->pnext != NULL)
{
ptmp = ptmp->pnext;
}
ptmp->pnext = pinsert;
}
plink->clen++;
return 0;
}

单向链表头删

int delete_link_head(Link_t *plink)
{
    if (is_empty_link(plink))
    {
        return -1;
    }

    Node_t *pfree = plink->phead;
    plink->phead = pfree->pnext;
    free(pfree);
    plink->clen--;

    return 0;
}

单向链表尾删

在这里插入图片描述

int delete_link_tail(Link_t *plink)
{
if (is_empty_link(plink))
{
return -1;
}
else if (NULL == plink->phead)
{
free(plink->phead);
plink->phead = NULL;
}
else
{
Node_t *ptmp = plink->phead;
while (ptmp->pnext->pnext != NULL)
{
ptmp = ptmp->pnext;
}
free(ptmp->pnext);
ptmp->pnext = NULL;
}
plink->clen--;
return 0;
}

单向链表查找

Node_t *find_link(Link_t *plink, int data)
{
    if (is_empty_link(plink))
    {
        return NULL;
    }

    Node_t *ptmp = plink->phead;
    while (ptmp)
    {
        if (ptmp->data == data)
        {
            return ptmp;
        }
        ptmp = ptmp->pnext;
    }

    return NULL;
}

单向链表修改

int change_link(Link_t *plink, int olddata, int newdata)
{
    Node_t *ptmp = NULL;
    ptmp = find_link(plink, olddata);
    if (NULL != ptmp)
    {
        ptmp->data = newdata;
        return 0;
    }

return -1;
}

内存泄露:
用户自己申请的堆区空间使用完没有及时释放则造成内存泄露。
检测程序有没有内存泄露:
valgrind:内存错误检测工具(GNU提供),可以检测程序运行过程中的内存泄露情况,以及野指针的
使用情况等。

单向链表判断是否有环:
使用快慢指针法:从起点开始,快指针一次走两步,慢指针一次走一步,若快指针最终走到了NULL
的位置,说明链表无环;如果快指针和满指针相遇了,则说明有环。

有环链表的环长:
从相遇点开始,让指针开始遍历链表,当该指针再次走到相遇点,则统计出了的个数为环长

求有环链表环的入口:
经过推算,相遇点到环入口长度等于开头到环入口的位置。
一个指针从想遇点开始走,一个指针从头走,当两个指针再次相遇,则为环形的入口。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值