C语言实现单链表的基本操作

1.链表出现的原因是顺序表的缺点

  • 顺序表在插入和删除运算必须移动大量(几乎一半)数据元素,效率低下。
  • 顺序表必须预先分配存储空间,造成空间利用率低,而且表的容量难以扩充。

2.链表的定义

通过一组任意的存储单元来存储线性表中的数据元素。

3.链表示意图

这里写图片描述

LinkList.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

#ifndef __LINKLIST_H__ 
#define __LINKLIST_H__ 

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

typedef int DataType;

typedef struct Node
{
    DataType data;
    struct Node* next;
}Node, *pNode, List, *pList;
//*pNode,*pList:指向节点的指针类型,但是*pNode是用来开辟新节点,或创建新的指向节点的指针;
//*pList用来创建新的指向链表头节点的指针

void InitLinkList(pList* pplist);//初始化头指针plist
pNode BuyNode(DataType d);//创建新节点
void DestroyLinkList(pList* pplist);//销毁链表
void PushBack(pList* pplist, DataType d);//尾部插入
void PopBack(pList* pplist);//尾部删除节点
void PushFront(pList* pplist, DataType d);//头部插入
void PopFront(pList* pplist);//头删
pNode Find(pList plist, DataType d);//查找某一元素

//在指定位置之前插入一个值 
void Insert(pList* pplist, pNode pos, DataType d);//指定位置前插入
//指定位置删除 
void Erase(pList* pplist, pNode pos);
void Remove(pList* pplist, DataType d);
void RemoveAll(pList* pplist, DataType d);
void EraseNotTailNode(pNode pos);
void PrintLinkList(pList plist);//打印链表
int GetListLength(pList plist);//获取链表长度
//链表面试题 

//1. 逆序打印单项链表 
void PrintTailToHead(pList plist);

#endif //__LINKLIST_H__
LinkList.c
#include"LinkList.h"

void InitLinkList(pList * pplist)
{
    assert(pplist != NULL);
    *pplist = NULL;
}

pNode BuyNode(DataType d)
{
    pNode newNode = (pNode)malloc(sizeof(Node));//开辟新节点
    newNode->data = d;
    newNode->next = NULL;
    return newNode;
}

void DestroyLinkList(pList * pplist)
{
    pNode cur = NULL;
    assert(pplist != NULL);
    cur = *pplist;
    while (cur)
    {
        pNode del = cur;
        cur = cur->next;
        free(del);
        del = NULL;
    }
    *pplist = NULL;
}

void PushBack(pList * pplist, DataType d)
{
    pNode newNode = BuyNode(d);//利用BuyNode创建新节点
    assert(pplist != NULL);
    if (*pplist == NULL)//空链表
    {
        *pplist = newNode;//将头指针和新节点挂链起来
    }
    else//非空链表
    {
        pNode cur = *pplist;
        while (cur->next != NULL)
        {
            cur = cur->next;
        }
        cur->next = newNode;
    }
}

void PopBack(pList * pplist)
{
    assert(pplist != NULL);
    if (*pplist == NULL)//没有节点
    {
        return;
    }
    if ((*pplist)->next == NULL)//一个节点
    {
        free(*pplist);
        *pplist = NULL;
    }
    else//一个以上的节点
    {
        pNode cur = *pplist;
        while (cur->next->next != NULL)
        {
            cur = cur->next;
        }
        free(cur->next);
        cur->next = NULL;
    }

}

void PushFront(pList * pplist, DataType d)
{
    pNode newNode = NULL;
    assert(pplist != NULL);
    newNode = BuyNode(d);
    newNode->next = *pplist;
    *pplist = newNode;
}

void PopFront(pList * pplist)
{
    assert(pplist != NULL);
    if (*pplist == NULL)//没有节点
    {
        return;
    }
    else//有节点
    {
        pNode del = *pplist;
        *pplist = del->next;
        free(del);
        del = NULL;
    }

}

pNode Find(pList plist, DataType d)
{
    pNode cur = plist;
    while (cur)
    {
        if (cur->data == d)
        {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;//没找到
}

void Insert(pList * pplist, pNode pos, DataType d)
{
    pNode newNode = NULL;
    assert(pplist != NULL);
    assert(*pplist != NULL);
    assert(pos != NULL);
    if (pos = *pplist)
    {
        newNode = BuyNode(d);
        newNode->next = *pplist;
        *pplist = newNode;
    }
    else
    {
        pNode cur = *pplist;
        while (cur && cur->next != pos)
        {
            cur = cur->next;
        }
        if (cur != NULL)
        {
            newNode = BuyNode(d);
            newNode->next = pos;
            cur->next = newNode;
        }
    }
}

void PrintLinkList(pList plist)
{
    pNode cur = plist;
    while (cur != NULL)
    {
        printf("%d-->", cur->data);
        cur = cur->next;
    }
    printf("Over\n");
}

int GetListLength(pList plist)
{
    pNode cur = plist;
    int count = 0;
    while (cur)
    {
        count++;
        cur = cur->next;
    }
    return count;
}

Test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"LinkList.h"
void test()
{
    Node* plist= NULL;//指向第一个节点的指针
    InitLinkList(&plist);//初始化plist为空指针,所以要传地址
    PushBack(&plist, 1);//传地址的原因:当链表中没有节点时,要改变plist,所以要传地址
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PushBack(&plist, 4);
    PrintLinkList(plist);
    /*DestroyLinkList(&plist);
    PrintLinkList(plist);*/
    printf("%d个节点\n", GetListLength(plist));
}
void TestPopBack()
{
    Node* plist = NULL;//指向第一个节点的指针
    InitLinkList(&plist);//初始化plist为空指针,所以要传地址
    PushBack(&plist, 1);//传地址的原因:当链表中没有节点时,要改变plist,所以要传地址
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PushBack(&plist, 4);
    PrintLinkList(plist);
    PopBack(&plist);
    PrintLinkList(plist);
    DestroyLinkList(&plist);
}
void TestPushFront()
{
    Node* plist = NULL;//指向第一个节点的指针
    PushFront(&plist, 1);
    PushFront(&plist, 2);
    PushFront(&plist, 3);
    PushFront(&plist, 4);
    PrintLinkList(plist);
    DestroyLinkList(&plist);
}
void TestPopFront()
{
    Node* plist = NULL;//指向第一个节点的指针
    PushFront(&plist, 1);
    PushFront(&plist, 2);
    PushFront(&plist, 3);
    PushFront(&plist, 4);
    PrintLinkList(plist);
    PopFront(&plist);
    PrintLinkList(plist);
    DestroyLinkList(&plist);
}
void TestFind()
{
    Node* plist = NULL;//指向第一个节点的指针
    pNode pos = NULL;
    PushFront(&plist, 1);
    PushFront(&plist, 2);
    PushFront(&plist, 3);
    PushFront(&plist, 4);
    PrintLinkList(plist);
    pos = Find(plist, 3);
    if (pos != NULL)
    {
        printf("%d\n", pos->data);
    }
    PrintLinkList(plist);
    DestroyLinkList(&plist);
}
void TestInsert()
{
    Node* plist = NULL;//指向第一个节点的指针
    pNode pos = NULL;
    PushFront(&plist, 1);
    PushFront(&plist, 2);
    PushFront(&plist, 3); 
    PushFront(&plist, 4);
    PrintLinkList(plist);
    pos = Find(plist, 1);
    if (pos != NULL)
    {
        Insert(&plist, pos, 5);
    }
    PrintLinkList(plist);
    DestroyLinkList(&plist);
}
int main()
{
    //test();
    //TestPopBack();
    //TestPushFront();
    //TestPopFront();
    //TestFind();
    TestInsert();
    system("pause");
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值