欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单链表的实现

程序员文章站 2022-05-06 12:41:54
...
1.单链表的介绍

    单链表链存储结构的存储分配以节点为单位,每个节点由节点数据和指针构成.单链表的结点通常定义成两个域:结点数据和指针域.。此篇文章先来讨论不带头结点不带环的链表
单链表的实现
    (1)初始化链表
    初始化一个链表也就是表示一个空链表,而要表示一个空链表,那就直接让这个链表所对应的头指针指向空即可
                                        单链表的实现

void LinkListInit(LinkNode** phead)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    *phead = NULL;
}

    (2)头插一个元素
    向链表中头插一个元素有两种可能,一种是链表中已经有元素了,另一种是链表中没有元素,即链表是一个空链表,这时就需要创建一个结点,然后修改头结点的指向,让其不再是空。而当链表不是空的时候,创建一个新结点,让这个新结点的next等于head,然后修改head就可以了
单链表的实现

void LinkListPushFront(LinkNode** phead, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)//链表为空
    {
        LinkListPushBack(phead, value);
        return;
    }
    LinkNode* new_head = LinkNodeCreate(value);
    new_head -> next = *phead;
    *phead = new_head;
}

单链表的实现
    (2)头删一个元素
    当链表不为空时,分为两种情况,链表只有一个元素,和链表元素多于一个。当链表只有一个元素时,直接将头指针所指向的结点销毁即可;当有多个结点时,就需要先定义一个新结点new_node记住当前的头指针所指向的结点,然后让头指针指向其对应结点的next所指向的结点,再销毁new_node所指向的结点
单链表的实现

void LinkListPopFront(LinkNode** phead)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    if((*phead) -> next == NULL)//链表只有一个元素
    {
        LinkListPopBack(phead);
        return;
    }
    LinkNode* new_head = *phead;
    *phead = new_head -> next;
    LinkNodeDestroy(&new_head);
}

单链表的实现
    (3)尾插一个元素
    尾插一个元素也分为两种情况:链表为空和链表不为空的情况。首先得创建一个结点,当链表为空时就和头插一样(不再叙述),当链表不为空时就定义一个新的头指针,让其遍历这个链表,知道找到最后一个元素,然后将其插入链表的末尾即可
单链表的实现

void LinkListPushBack(LinkNode** phead, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        LinkNode* new_node = LinkNodeCreate(value);
        *phead = new_node;
        return;
    }
    LinkNode* cur = *phead;
    for(; cur -> next != NULL; cur = cur -> next)
    {
        ;
    }
    LinkNode* new_node = LinkNodeCreate(value);
    cur -> next = new_node;
}

单链表的实现
    (4)尾删一个元素
     尾删一个元素也分为两种情况,只有一个元素和多余一个结点。当只有一个结点时就直接将头指针所指向的元素销毁即可,当多余一个结点时就遍历整个链表知道头指针所指向的元素的next指向空时就删除头指针所指向的这个结点(释放内存)
单链表的实现

void LinkListPopBack(LinkNode** phead)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    LinkNode* cur = *phead;
    if(cur -> next == NULL)//只有一个结点
    {
        LinkNodeDestroy(phead);
        return;
    }
    for(; cur -> next -> next != NULL; cur = cur -> next)
    {
        ;
    }
    LinkNodeDestroy(&(cur -> next));

}

单链表的实现
    (5)查找某个元素的位置
    定义一个指针指向首元素,然后让这个指针所指向的节点的数据和目标元素比较,如果相等便返回定义的指针的值,如果不相等就一次往后便利,直到这个指针指向空时便说明没有找到,此时返回NULL即可(在此便不画图了)

LinkNode* LinkListFind(LinkNode* phead, LinkNodeType to_find)
{
    if(phead == NULL)
    {
        return NULL;//非法输入
    }
    LinkNode* cur = phead;
    for(; cur != NULL; cur = cur -> next)
    {
        if(cur -> data== to_find)
        {
            return cur;
        }
    }
    return NULL;
}

    (6)在pos之前插入某个元素
    也是分为两种情况,空链表和链表不为空两种。有两种方法,遍历链表和 不遍历链表的两种方法。
    (1 遍历整个链表
    定义指针cur让其指向链表的首元素,依次遍历整个链表,将cur指向元素的next与pos比较当其相等时将新结点的next等于pos所指向的元素,再将cur的next指向新结点
单链表的实现
    (2 不用遍历整个链表
单链表的实现

/*
 *
 * 遍历链表在 pos 前插入一个元素
 *
 */
void LinkListInsert(LinkNode** phead, LinkNode* pos, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL || (*phead) -> next == NULL)//只有一个元素,或者没有元素
    {
        LinkListPushFront(phead, value);
        return;
    }
    LinkNode* cur = *phead;
    LinkNode* new_node = LinkNodeCreate(value);
    while(1)
    {
        if(cur -> next == pos)
        {
            new_node -> next = pos;
            cur -> next = new_node;
            return;
        }
        cur = cur -> next;
    }
}

/*
 *
 * 不用遍历链表在 pos 前插入一个元素
 *
 */

void LinkNodeInsertBefor(LinkNode** phead, LinkNode* pos, LinkNodeType value)
{
    if(phead == NULL || pos == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)//链表为空
    {
        LinkListPushFront(phead, value);
        return;
    }
    LinkNode* new_node = LinkNodeCreate(value);
    new_node -> data = pos -> data;
    pos -> data = value;
    new_node -> next = pos -> next;
    pos -> next = new_node;
}

单链表的实现
    (6)在pos之后插入某个元素
     在pos之后插入一个结点也分为两种情况,链表为空和链表不为空,当链表为空时就和尾插一样,于是调用尾插函数,当链表不为空时,就直接将生成的新结点的next指向pos指针指向结点的next指针所指向的结点,然后再将pos指针所指向的结点的next指向新结点

void LinkListInsertAfter(LinkNode** phead, LinkNode* pos, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)//链表为空
    {
        LinkListPushBack(phead, value);
        return;
    }

    LinkNode* new_node = LinkNodeCreate(value);
    new_node -> next = pos -> next;
    pos -> next = new_node;
}

单链表的实现
    (7)删除指定位置的元素
        删除指定位置处的元素也分为两种情况。第一种就是当链表只有一个结点时,就直接释放头指针所指向的结点;当结点多于一个元素时,就先定义一个指针等于头指针,然后便利链表,知道这个指针所指向的结点的next等于pos所指向的结点时,就先定义一个指针to_eraser记录pos的位置,然后再让定义的这个指针所指向元素的next指向pos所指向元素的next所指的元素,最后销毁to_eraser指针所指向的元素即可

/*
 *
 * 删除指定位置 pos 处的元素
 *
 */

void LinkListEraser(LinkNode** phead, LinkNode* pos)
{
    if(phead == NULL || pos == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    if((*phead) -> next == NULL)
    {
        LinkNodeDestroy(phead);
        return;
    }
    LinkNode* cur = *phead;
    while(cur -> next != pos)
    {
        cur = cur -> next;
    }
    LinkNode* to_eraser = cur -> next;
    LinkNodeDestroy(&pos);
    cur -> next = to_eraser -> next;
}

/*
 *
 * 删除指定位置 pos 处的元素
 *
 */

void LinkListEraser2(LinkNode** phead, LinkNode* pos)
{
    pos -> data = (pos -> next) -> data;
    LinkNode* to_eraser = pos -> next;
    pos -> next = to_eraser -> next;
    LinkNodeDestroy(&(to_eraser));
}

单链表的实现
    (8)删除指定值的元素
        删除指定值得元素必须先让删除的这个值与链表的每个元素进行比较,如果没有这个元素就直接返回,如果有这个元素则删除这个元素,期间也需要遍历链表

/*
 *
 * 删除指定值的元素
 *
 */

void LinkListRemove(LinkNode** phead, LinkNodeType to_delete)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    LinkNode* cur;
    cur = *phead;
    while(cur != NULL)
    {
        if(cur -> data == to_delete)
        {
            break;
        }
        cur = cur -> next;
    }
    if(cur == NULL)
    {
        return;
    }
    LinkListEraser(phead, cur);
    return;
}

单链表的实现
    (9)删除指定值的所有元素
        删除指定值的所有元素则和删除指定值的元素唯一的不同点就是定义一个指针指向链表的首结点,然后依次遍历这个链表,如果发现结点的data和指定值相等就删除这个结点,同时指针向后移动,直到链表的结尾(定义的结点指向空)

void LinkListRemoveAll(LinkNode** phead, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    LinkNode* cur = *phead;
    while(cur != NULL)
    {
        if(cur -> data == value)
        {
            LinkListRemove(phead, value);
        }
        cur = cur -> next;
    }
}

单链表的实现
    (10)求链表长度
        定义一个指针等于头结点,先判断头结点是否为空,当头结点等于空的时候说明链表为空,这是返回0即可,当头结点不为空的时候,就定义一个计数器,然后让所定义的这个指针一次遍历链表,指针后移一次,计数器加1,直到指针指向空。

size_t LinkNodeSize(LinkNode* phead)
{
    if(phead == NULL)
    {
        return 0;
    }
    int count = 0;
    LinkNode* cur = phead;
    for(; cur != NULL; cur = cur -> next)
    {
        count ++;
    }
    return count;
}

                单链表的实现

2.整体代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linklist.h"

#define TESTHEADER printf("\n===============%s================\n", __FUNCTION__)

/*
 *
 * 初始化链表
 *
 */ 

void LinkListInit(LinkNode** phead)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    *phead = NULL;
}
//////////////////////////////////////////////////////////////////////////////
////LinkListInit的测试代码
/////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////
////测试代码
/////////////////////////////////////////////////////////////////////////////

void TestPrintChar(LinkNode* phead, char* msg)
{
    printf("%s\n",msg);
    if(phead == NULL)
    {
        return;
    }
    LinkNode* cur = phead;
    for(; cur != NULL; cur = cur -> next)
    {
        printf("[%c | %p] -> ", cur -> data, cur -> next);
    }
    printf("\n");
}


/*
 * 
 * 创建一个新结点
 *
 */

LinkNode* LinkNodeCreate(LinkNodeType value)
{
    LinkNode* new_node = (LinkNode*)malloc(sizeof(LinkNode));
    new_node -> data = value;
    new_node -> next = NULL;
}

//////////////////////////////////////////////////////////////////////////////
////以下是LinkNodeCreate的测试代码
/////////////////////////////////////////////////////////////////////////////

void TestCreat()
{
    LinkNode* head;
    LinkListInit(&head);
    head = LinkNodeCreate('a');
    TestPrintChar(head, "创建一个新结点:");
}

/*
 *
 * 销毁一个结点
 *
 */
void LinkNodeDestroy(LinkNode** phead)
{
    free(*phead);
    *phead = NULL;
}

/*
 *
 * 尾插一个元素
 *
 */

void LinkListPushBack(LinkNode** phead, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        LinkNode* new_node = LinkNodeCreate(value);
        *phead = new_node;
        return;
    }
    LinkNode* cur = *phead;
    for(; cur -> next != NULL; cur = cur -> next)
    {
        ;
    }
    LinkNode* new_node = LinkNodeCreate(value);
    cur -> next = new_node;
}

//////////////////////////////////////////////////////////////////////////////
////LinkListPushBack的测试代码
//////////////////////////////////////////////////////////////////////////////

void PushBackTest()
{
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushBack(&head, 'x');
    LinkListPushBack(&head, 'y');
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'q');
    TestPrintChar(head, "尾插一个元素:");
}

/*
 *
 * 尾删一个元素
 *
 */

void LinkListPopBack(LinkNode** phead)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    LinkNode* cur = *phead;
    if(cur -> next == NULL)//只有一个结点
    {
        LinkNodeDestroy(phead);
        return;
    }
    for(; cur -> next -> next != NULL; cur = cur -> next)
    {
        ;
    }
    LinkNodeDestroy(&(cur -> next));

}

////////////////////////////////////////////////////////////////////////////
////LinkListPopBack的测试代码
///////////////////////////////////////////////////////////////////////////

void PopBackTest()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    //LinkListPushBack(&head, 'x');
    //TestPrintChar(head, "尾插一个元素");
    //LinkListPopBack(&head);

    //TestPrintChar(head, "尾删只有一个元素的链表:");

    LinkListPushBack(&head, 'y');
    LinkListPushBack(&head, 'a');
    LinkListPushBack(&head, 'q');
    LinkListPushBack(&head, 'z');
    TestPrintChar(head, "尾插三个元素");

    LinkListPopBack(&head);
    TestPrintChar(head, "尾删一个三个元素");
}

/*
 *
 * 头插
 *
 */

void LinkListPushFront(LinkNode** phead, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)//链表为空
    {
        LinkListPushBack(phead, value);
        return;
    }
    LinkNode* new_head = LinkNodeCreate(value);
    new_head -> next = *phead;
    *phead = new_head;
}

///////////////////////////////////////////////////////////////////////////////////
//////LinkListPushFront的测试代码
///////////////////////////////////////////////////////////////////////////////////

void TestPushFront()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'b');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    TestPrintChar(head, "头插四个元素");
}

/*
 *
 *头删
 *
 */

void LinkListPopFront(LinkNode** phead)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    if((*phead) -> next == NULL)//链表只有一个元素
    {
        LinkListPopBack(phead);
        return;
    }
    LinkNode* new_head = *phead;
    *phead = new_head -> next;
    LinkNodeDestroy(&new_head);
}

////////////////////////////////////////////////////////////////////////////////////////////
////LinkListPopFront的测试代码
////////////////////////////////////////////////////////////////////////////////////////////

void TestPopFront()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    LinkListPopFront(&head);
    TestPrintChar(head, "头删空链表:");

    LinkListPushFront(&head, 'a');
    TestPrintChar(head, "头插一个元素:");
    LinkListPopFront(&head);
    TestPrintChar(head, "头删一个元素:");

    LinkListPushFront(&head, 'b');
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    TestPrintChar(head, "头插六个个元素:");
    LinkListPopFront(&head);
    LinkListPopFront(&head);
    TestPrintChar(head, "头删两个元素:");

}

/*
 *
 * 查找 to_find 元素,并且返回其对应的地址
 * 如果没有找到,就返回空
 *
 */

LinkNode* LinkListFind(LinkNode* phead, LinkNodeType to_find)
{
    if(phead == NULL)
    {
        return NULL;//非法输入
    }
    LinkNode* cur = phead;
    for(; cur != NULL; cur = cur -> next)
    {
        if(cur -> data== to_find)
        {
            return cur;
        }
    }
    return NULL;
}

//////////////////////////////////////////////////////////////////////////
////LinkListFind的测试代码
//////////////////////////////////////////////////////////////////////////

void TestFind()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'b');
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    LinkNode* ret = LinkListFind(head, 'a');
    TestPrintChar(head,"头插六个元素");
    printf("&a = %p\n", ret);
}

/*
 *
 *在 pos 之前插入元素 value
 *
 */

void LinkListInsert(LinkNode** phead, LinkNode* pos, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL || (*phead) -> next == NULL)//只有一个元素,或者没有元素
    {
        LinkListPushFront(phead, value);
        return;
    }
    LinkNode* cur = *phead;
    LinkNode* new_node = LinkNodeCreate(value);
    while(1)
    {
        if(cur -> next == pos)
        {
            new_node -> next = pos;
            cur -> next = new_node;
            return;
        }
        cur = cur -> next;
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
////LinkNodeInsert的测试代码
/////////////////////////////////////////////////////////////////////////////////////////

void TestInsert()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    LinkListInsert(&head, head -> next, '1');
    TestPrintChar(head, "往e前面插入元素‘1’:");
}

/*
 *
 * 在 pos 之后插入一个元素
 *
 */

void LinkListInsertAfter(LinkNode** phead, LinkNode* pos, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)//链表为空
    {
        LinkListPushBack(phead, value);
        return;
    }

    LinkNode* new_node = LinkNodeCreate(value);
    new_node -> next = pos -> next;
    pos -> next = new_node;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/////LinkListInsertAfer的测试代码
/////////////////////////////////////////////////////////////////////////////////////////////////

void TestInsertAfter()
{
    TESTHEADER;
    LinkNode* head; 
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    LinkListInsertAfter(&head, head -> next -> next, '1');
    TestPrintChar(head, "往d后面插入元素‘1’:");
}

/*
 *
 * 删除指定位置 pos 处的元素
 *
 */

void LinkListEraser(LinkNode** phead, LinkNode* pos)
{
    if(phead == NULL || pos == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    if((*phead) -> next == NULL)
    {
        LinkNodeDestroy(phead);
        return;
    }
    LinkNode* cur = *phead;
    while(cur -> next != pos)
    {
        cur = cur -> next;
    }
    LinkNode* to_eraser = cur -> next;
    LinkNodeDestroy(&pos);
    cur -> next = to_eraser -> next;
}

/////////////////////////////////////////////////////////////////////////////////////
////LinkListEraser的测试代码
//////////////////////////////////////////////////////////////////////////////////////

void TestEraser()
{
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    TestPrintChar(head, "头插5个元素:");
    LinkListEraser(&head, head -> next);
    TestPrintChar(head, "删除e:");
}

/*
 *
 * 删除指定位置 pos 处的元素
 *
 */

void LinkListEraser2(LinkNode** phead, LinkNode* pos)
{
    pos -> data = (pos -> next) -> data;
    LinkNode* to_eraser = pos -> next;
    pos -> next = to_eraser -> next;
    LinkNodeDestroy(&(to_eraser));
}

///////////////////////////////////////////////////////////////////////////////
////LinkListEraser2的测试代码
////////////////////////////////////////////////////////////////////////////////

void TestEraser2()
{
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    TestPrintChar(head, "头插5个元素:");
    LinkListEraser2(&head, head -> next);
    TestPrintChar(head, "删除e:");
}

/*
 *
 * 不用遍历链表在 pos 前插入一个元素
 *
 */

void LinkNodeInsertBefor(LinkNode** phead, LinkNode* pos, LinkNodeType value)
{
    if(phead == NULL || pos == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)//链表为空
    {
        LinkListPushFront(phead, value);
        return;
    }
    LinkNode* new_node = LinkNodeCreate(value);
    new_node -> data = pos -> data;
    pos -> data = value;
    new_node -> next = pos -> next;
    pos -> next = new_node;
}

/////////////////////////////////////////////////////////////////////////////////////
////LinkNodeInsertBefor的测试代码
/////////////////////////////////////////////////////////////////////////////////////

void TestInsertBefor()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    LinkListInsert(&head, head -> next, '1');
    TestPrintChar(head, "往e前面插入元素‘1’:");
}

/*
 *
 * 删除指定值的元素
 *
 */

void LinkListRemove(LinkNode** phead, LinkNodeType to_delete)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    LinkNode* cur;
    cur = *phead;
    while(cur != NULL)
    {
        if(cur -> data == to_delete)
        {
            break;
        }
        cur = cur -> next;
    }
    if(cur == NULL)
    {
        return;
    }
    LinkListEraser(phead, cur);
    return;
}

/////////////////////////////////////////////////////////////////////////////
/////LinkListRemove的测试代码
/////////////////////////////////////////////////////////////////////////////

void TestRemove()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'e');
    LinkListPushFront(&head, 'f');
    TestPrintChar(head, "插入5个元素:");
    LinkListRemove(&head, 'e');
    TestPrintChar(head, "删除‘e’:");
}

/*
 *
 * 删除指定值得所有元素
 *
 */

void LinkListRemoveAll(LinkNode** phead, LinkNodeType value)
{
    if(phead == NULL)
    {
        return;//非法输入
    }
    if(*phead == NULL)
    {
        return;//链表为空
    }
    LinkNode* cur = *phead;
    while(cur != NULL)
    {
        if(cur -> data == value)
        {
            LinkListRemove(phead, value);
        }
        cur = cur -> next;
    }
}

///////////////////////////////////////////////////////////////////////////////
////LinkListRemove的测试代码
///////////////////////////////////////////////////////////////////////////////

void TestRemoveAll()
{
    TESTHEADER;
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    TestPrintChar(head, "插入9个元素");
    LinkListRemoveAll(&head, 'a');
    TestPrintChar(head, "删除链表中的'a':");

}

/*
 *
 * 求链表元素个数
 *
 */

size_t LinkNodeSize(LinkNode* phead)
{
    if(phead == NULL)
    {
        return 0;
    }
    int count = 0;
    LinkNode* cur = phead;
    for(; cur != NULL; cur = cur -> next)
    {
        count ++;
    }
    return count;
}

/////////////////////////////////////////////////////////////////////////////////////////
//////LinkNodeSize的测试代码
/////////////////////////////////////////////////////////////////////////////////////////

void TestSize()
{
    LinkNode* head;
    LinkListInit(&head);
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    LinkListPushFront(&head, 'a');
    LinkListPushFront(&head, 'c');
    LinkListPushFront(&head, 'd');
    int count = 0;
    count = LinkNodeSize(head);
    printf("expected count = %d, actuall count = %d\n", 9, count);
}

int main()
{
    TestCreat();
    PushBackTest();
    PopBackTest();
    TestPushFront();
    TestPopFront();
    TestFind();
    TestInsert();
    TestInsertAfter();
    TestEraser();
    TestEraser2();
    TestInsertBefor();
    TestRemove();
    TestRemoveAll();
    TestSize();
    return 0;
}

//linklist.h
#include<stdio.h>

#pragma once

typedef char LinkNodeType;

typedef struct LinkNode
{
   LinkNodeType data;
   struct LinkNode* next;
}LinkNode;

typedef LinkNode* PLinkNode;

void LinkListInit(LinkNode** phead);

void LinkListPushBack(LinkNode** phead, LinkNodeType value);

LinkNode* LinkNodeCreate(LinkNodeType value);

void LinkListPopFront(LinkNode** phead);

void LinkListPushFront(LinkNode** phead, LinkNodeType value);

void LinkListPopBack(LinkNode** phead);

void LinkNodeDestroy(LinkNode** phead);

LinkNode* LinkListFind(LinkNode* phead, LinkNodeType to_find);

void LinkListInsert(LinkNode** phead, LinkNode* pos, LinkNodeType value);

void LinkListInsertAfer(LinkNode** phead, LinkNode* pos, LinkNodeType value);

void LinkListInsertBefor(LinkNode** phead, LinkNode* pos, LinkNodeType value);

void LinkListEraser(LinkNode** phead, LinkNode* pos);

void LinkListEraser2(LinkNode** phead, LinkNode* pos);

void LinkListRemove(LinkNode** phead, LinkNodeType to_delet);

void LinkListRemoveAll(LinkNode** phead, LinkNodeType value);

void LinkListSize(LinkNode* phead);
相关标签: 单链表的实现