【C语言】单链表的实现

单链表

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。

单链表结构如下:

typedef int DataType;
typedef struct Node
{
    struct Node* next;   //指向下一个节点的指针
    DataType data;       //当前节点存放的数据
}Node,*pLinkNode;

注意:

Node* plist;
pLinkNode pplist;

①pLinkNode和Node是不同名字的同一个指针类型(命名的不同是为了概念上更明确)
②*pLinkNode类型的指针变量pplist表示它是单链表的头指针
③Node类型的指针变量plist表示它是指向某一结点的指针

单链表的一些基本操作实现如下:

void InitList(pLinkNode* pplist)
{
    assert(pplist);
    *pplist = 0;  //初始化为空指针
}
void PrintList(pLinkNode pplist)       
{
    assert(pplist);
    pLinkNode begin = pplist;
    printf("List->");
    while (begin)
    {
        printf("%d->", begin->data);
        begin = begin->next;
    }
    printf("NULL\n");
}
pLinkNode GreateNode(DataType data)
{
    pLinkNode newplist = (pLinkNode)malloc(sizeof(Node));
    newplist->data = data;
    newplist->next = NULL;
    return newplist;
}
void PushBack(pLinkNode* pplist, DataType data)
{
    assert(pplist);
    if (*pplist == NULL)
    {
        *pplist = GreateNode(data);
    }
    else
    {
        pLinkNode end = *pplist;
        while (end->next != NULL)
        {
            end = end->next;
        }
        end->next = GreateNode(data);
    }
}
void PopBack(pLinkNode* pplist)
{
    assert(pplist);
    if (*pplist == NULL)
    {
        perror("error:");
        return;
    }
    else
    {
        pLinkNode prev, end;
        prev = *pplist;
        end = *pplist;
        while (end->next != NULL)
        {
            prev = end;
            end = end->next;
        }
        if (end == (*pplist))
        {
            *pplist = NULL;
        }
        else
        {
            prev->next = NULL;
        }
        free(end);
    }
}
void PushFront(pLinkNode* pplist, DataType data)   
{
    assert(pplist);
    if (*pplist == NULL)
    {
        *pplist = GreateNode(data);
    }
    else
    {
        pLinkNode ret = GreateNode(data);
        ret->next = *pplist;
        *pplist = ret;
    }
}

void PopFront(pLinkNode* pplist)
{
    assert(pplist);
    if (*pplist == NULL)
    {
        perror("error:");
        return;
    }
    else
    {
        pLinkNode begin = *pplist;
        if ((*pplist)->next == NULL)
        {
            *pplist = NULL;
        }
        else
        {
            *pplist = (*pplist)->next;
        }
        free(begin);
    }
}
void GetListLength(pLinkNode plist)         
{
    assert(plist);
    int count = 0;
    pLinkNode begin = plist;
    while (begin)
    {
        count++;
        begin = begin->next;
    }
    printf("ListLength Is %d\n", count);
}
pLinkNode Find(pLinkNode plist, DataType data)
{
    assert(plist);
    pLinkNode begin = plist;
    while (begin)
    {
        if (begin->data == data)
        {
            return begin;
        }
        begin = begin->next;
    }
    return NULL;
}
void Insert(pLinkNode* pplist, pLinkNode n,DataType data)//n是在主函数内用Find查找
{                                                        //在节点n后面插入一个数据
    assert(pplist);
    if (*pplist == NULL || n == NULL)
    {
        perror("error:");
        return;
    }
    pLinkNode ret = GreateNode(data);
    ret->next = n->next;
    n->next = ret;
}
void Remove(pLinkNode* pplist, pLinkNode n)//删除节点n
{
    assert(pplist);
    if (*pplist == NULL || n == NULL)
    {
        perror("error:");
        return;
    }
    if (n == *pplist)
    {
        *pplist = (*pplist)->next; //包括只有一个节点的情况
        free(n);
        return;
    }
    pLinkNode prev, ret;
    prev = *pplist;
    ret = *pplist;
    while (ret->next != NULL)
    {
        prev = ret;
        ret = ret->next;
        if (ret == n)
        {
            prev->next = ret->next;
            free(n);
            return;
        }
    }
}
void Erase(pLinkNode* pplist, DataType data, int flag)
{
    assert(pplist);
    if (*pplist == NULL)
    {
        perror("error:");
        return;
    }
    pLinkNode ret;
    do
    {
        ret = Find(*pplist, data);
        if (ret != NULL)
        {
            Remove(pplist, ret);
        }
    } while (flag != 0 && ret);
}

常见的单链表面试题如下:

void PrintBack(pLinkNode plist)       //从尾到头打印单链表
{
    assert(plist);
    if (plist->next != NULL)
    {
        PrintBack(plist->next);       //递归调用
    }
    printf("%d->", plist->data);
}
void Del_MidNode(pLinkNode n)        //删除一个无头的非尾结点a
{
    if (n == NULL)
    {
        printf("Invaid n\n");
        return;
    }
    pLinkNode ret = n->next;
    n->data = ret->data;
    n->next = ret->next;
    free(ret);
}
void PushNode(pLinkNode n, DataType data)//在无头单链表的一个非头节点前插入一个节点
{
    if (n == NULL)
    {
        printf("Invaid n\n");
        return;
    }
    pLinkNode ret = GreateNode(n->data);
    pLinkNode tmp = n->next;
    n->data = data;
    ret->next = tmp;
    n->next = ret;
}
void JosephCycle(pLinkNode plist, int Cycle)   //单链表实现的瑟夫环
{
    assert(plist);
    pLinkNode begin = plist;
    int k = Cycle;
    while (begin->next != begin)
    {
        int count = 1;
        while (count++ != k)
        {
            begin = begin->next;
        }
        printf("del :%d->",begin->data);
        pLinkNode del = begin->next;
        begin->data = del->data;
        begin->next = del->next;
    }
}
void Reverse(pLinkNode* pplist)   //逆置(翻转单链表)
{
    assert(pplist);
    if (*pplist == NULL)
    {
        perror("error:");
        return;
    }
    pLinkNode begin = (*pplist)->next;
    (*pplist)->next = NULL;
    while (begin)
    {
        pLinkNode ret = begin;
        begin = begin->next;
        ret->next = *pplist;
        *pplist = ret;
    }
}
void BubbSort(pLinkNode* pplist)  //冒泡排序
{
    assert(pplist);
    if (*pplist == NULL || (*pplist)->next == NULL)
    {
        return;
    }
    pLinkNode prev, tmp, end;
    end = NULL;
    while (end != *pplist)
    {
        prev = *pplist;            //每次从头开始比较
        tmp = (*pplist)->next;
        while (tmp != end)
        {
            if (prev->data > tmp->data)
            {
                int ret = prev->data;
                prev->data = tmp->data;
                tmp->data = ret;
            }
            prev = prev->next;
            tmp = tmp->next;
        }
        end = prev;
    }
}
pLinkNode Merge(pLinkNode plist1, pLinkNode plist2)//合并两个有序单链表,合并后依然有序
{
    if (plist1 == NULL)
    {
        return plist2;
    }
    if (plist2 == NULL)
    {
        return plist1;
    }
    if (plist1 == plist2)
    {
        return plist1;
    }
    pLinkNode plist,end;
    if (plist1->data < plist2->data)
    {
        plist = plist1;
        plist1 = plist1->next;
    }
    else
    {
        plist = plist2;
        plist2 = plist2->next;
    }
    end = plist;
    while (plist1 && plist2)
    {
        pLinkNode tmp;
        if (plist1->data < plist2->data)
        {
            tmp = plist1;
            plist1 = plist1->next;
        }
        else
        {
            tmp = plist2;
            plist2 = plist2->next;
        }
        end->next = tmp;
        end = tmp;
    }
    if (plist1)
    {
        end->next = plist1;
    }
    else if (plist2)
    {
        end->next = plist2;
    }
    return plist;
}
pLinkNode FindMidNode(pLinkNode plist)//查找单链表的中间节点,要求只能遍历一次链表。
{
    assert(plist);
    pLinkNode slow, fast;
    int flag = 0;
    slow = plist;
    fast = plist;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        flag = 1;
        if (fast == NULL)     //双数的时候
        {
            return slow;
        }
    }
    if (flag)                //单数的时候
    {
        return slow;
    }
    return NULL;
}

总结:

单链表优点:

单链表中插入或者删除一个节点相对线性表比较高效,即找到链表表中第i-1个结点,然后修改其指向后继的指针,无需移动大量数据。

单链表缺点:

单链表是链式存取的结构,为找第 i 个数据元素,必须先找到第 i-1 个数据元素,即不支持随机访问。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值