数据结构-实现单链表基本操作

首先要认识单链表:
单链表大致可以分为八种:
带头的,不带头的
带环的,不带环的
单向的,双向的

这里写代码片

我实现的功能如下:

void LinkListInit(LinkNode** phead);//初始化链表

void LinkListPrintChar(LinkNode* head,const char* msg);//打印链表

void LinkListPushBack(LinkNode** phead, LinkType value);//尾插 

void LinkListPopBack(LinkNode** phead);//尾删 

void LinkListPushFront(LinkNode** phead, LinkType value); //头插
void LinkListPopFront(LinkNode** phead); //头删

LinkNode* LinkListFind(LinkNode* head, LinkType to_find);//查找元素地址 

void LinkListInsert(LinkNode** head, LinkNode* pos, LinkType value);//pos前插入

void LinkListInsert2(LinkNode** phead, LinkNode* pos, LinkType value);//不允许遍历链表, 在 pos之前插入 

void LinkListInsertAfter(LinkNode* pos, LinkType value); //pos后插入

void LinkListErase(LinkNode** phead, LinkNode* pos); //删除指定地址的元素

实现如下:

初始化

初始化因为要使头指针指向空,所以

 19 void LinkListInit(LinkNode** phead)
 20 {
 21     if(phead==NULL)
 22     {
 23         return;
 24         //非法输入
 25     }
 26     *phead=NULL;
 27 }

这里写图片描述

尾插尾删

与顺序表基本相似,注意对指针的处理。

void LinkListPushBack(LinkNode** phead, LinkType value)                                                                                             
{
    if(phead==NULL)
    {
        return;
    }
    if(*phead==NULL)
    {
        //空链表
        LinkNode* new_node=CreatNode(value);
        *phead=new_node;
        return;
    }
    //链表非空的情况
    LinkNode* cur=*phead;
    while(cur->next!=NULL)
    {
        cur=cur->next;
    }
    LinkNode* new_node=CreatNode(value);
    cur->next=new_node;
}
void LinkListPopBack(LinkNode** phead)
{
    if(phead==NULL)
    {
        return;
    }
    if(*phead==NULL)
    {
        //空链表无法删除
        return;
    }
    if((*phead)->next==NULL)
    {
        DestroyNode(*phead);
        *phead=NULL;
        return;
    }
    LinkNode* cur=*phead;
    LinkNode* pre=NULL;
    while(cur->next!=NULL)
    {
        pre=cur;
        cur=cur->next;
    }
    DestroyNode(cur);
    pre->next=NULL;

}  

这里写图片描述

头删头插

void LinkListPushFront(LinkNode** phead, LinkType value)
{
    if(phead==NULL)
    {
        return;
    }
    LinkNode* new_node=CreatNode(value);
    new_node->next=*phead;
    *phead=new_node;
}

void LinkListPopFront(LinkNode** phead)
{
    if(phead==NULL)
    {
        return;
    }
    LinkNode* cur=*phead;
    *phead=(*phead)->next;
    DestroyNode(cur);
}

这里写图片描述

查找元素下标

成功:返回元素的地址
失败:返回NULL

LinkNode* LinkListFind(LinkNode* head, LinkType to_find)
{
    if(head==NULL)
    {
        return;
    }
    LinkNode* cur=head;
    for(;cur!=NULL;cur=cur->next)
    {
        if(cur->data==to_find)  
        {
            return cur;
        }
    }
    return NULL;
}

这里写图片描述

pos前插入元素

void LinkListInsert(LinkNode** phead, LinkNode* pos, LinkType value)
{
    if(phead==NULL||pos==NULL)
    {
        return;
    }
    if(*phead==pos)
    {
        LinkListPushFront(phead,value);
        return;
    }
    LinkNode* cur=*phead;
    while(cur!=NULL)
    {
        //printf("进入此\n");
        if(cur->next==pos)
        {
            LinkNode* new_node=CreatNode(value);
            cur->next=new_node;
            new_node->next=pos;
            return;
        }
        cur=cur->next;
    }
}

这里写图片描述

pos后面插入一个元素

void LinkListInsertAfter(LinkNode* pos, LinkType value)
{
    if(pos==NULL)
    {
        return;
    }
    LinkNode* new_node=CreatNode(value);
    new_node->next=pos->next;
    pos->next=new_node;
}

这里写图片描述

不允许遍历,在pos前插入元素

将前插转换为后插问题,再将这两个节点的值交换

void LinkListInsert2(LinkNode** phead, LinkNode* pos, LinkType value)
{
    if(phead==NULL)
    {
        return;
    }
    LinkListInsertAfter(pos,value);
    LinkType tmp=pos->data;
    pos->data=pos->next->data;
    pos->next->data=tmp;
}

这里写图片描述

删除某个地址上的元素

时间复杂度:O(n^2)

void LinkListErase(LinkNode** phead, LinkNode* pos)
{
    if(phead==NULL||pos==NULL)
    {
        return;
    }
    if(*phead==NULL)
    {
        return;//空链表
    }
    if(*phead==pos)
    {
        LinkListPopFront(phead);
        return;
    }
    LinkNode* cur=*phead;
    while(cur!=NULL)
    {
        if(cur->next==pos)
            break;
        cur=cur->next;
    }
    if(cur->next==NULL)
    {
        return;
    }
    cur->next=pos->next;
    DestroyNode(pos);
}

这里写图片描述
时间复杂度:O(1)

void LinkListErase2(LinkNode** phead, LinkNode* pos)
{
    if(phead==NULL)
    {
        return;
    }
    if(*phead==NULL)
    {
        return;
    }
    LinkNode* to_destroy=pos->next;
    pos->data=pos->next->data;
    pos->next=pos->next->next;
    DestroyNode(to_destroy);

}

这里写图片描述

删除指定值的元素

void LinkListRemove(LinkNode** phead, LinkType to_delete)
{
    if(phead==NULL)
    {
        return;
    }
    if(*phead==NULL)
    {
        return;//空链表
    }
    LinkNode* pos=NULL;
    pos=LinkListFind(*phead,to_delete);
    LinkListErase(phead,pos);

这里写图片描述

对单链表判空

链表为空,返回1
链表非空,返回0

int LinkListEmpty(LinkNode* head)
{
    if(head==NULL)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

这里写图片描述

链表的元素个数

返回链表元素的个数

size_t LinkListSize(LinkNode* head)
{
    size_t count=0;
    LinkNode* cur=head;
    for(;cur!=NULL;cur=cur->next)
    {
        count++;
    }
    return count;
}

这里写图片描述

逆序打印单链表

void LinkListReversePrint(LinkNode* head)
{
    if(head==NULL)
    {
        return;
    }
    if(head==NULL)
    {
        return;
    }
    LinkListReversePrint(head->next);
    printf("[%c|%p] ",head->data,head);
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值