链表的C语言实现---接口函数丰富的单向链表

为什么要写这篇

本意是为了将扫描到的蓝牙设备列表 按照接收灵敏度存放到链表中,我一个同事是这么做的,我当时用结构体数组排序不香吗反驳了回去,因为自己没怎么用过链表,我自己都怀疑自己有点儿酸葡萄心理,然后就自己查资料实现了个链表。主要还是自己理解,参考资料有C Primer Plus的链表(抽象数据类型ADT) 和 数据结构笔记【单链表】

说在前面的话

要测试的话,请先搭建环境:编译C代码环境搭建

要源文件的话,请点击链接:LinkedList.zip

链表的实现有很多种,但更重要的是自己有清晰的思路,知道会用到哪些操作,这篇文章真是费时不少,收获嘛,还没有将链表结点用到实处,真是那句话说得好:行百里者半九十。

为链表添加了一个记录项数的变量,带来的直接好处是判断为空为满直接将该变量与数值做比较即可,否则就是查询头结点是否为NULL(为空判断),是否已经申请不到内存(为满判断),那样并不适用于实际使用情况。这是一个很关键的变量。

关于只有指向头结点的指针,没有指向尾结点的指针,可能也是为了和之前实现的递推均值滤波算法---链式队列实现相区分开吧,会不会有什么影响?对于单向链表来说,指向尾结点的指针只能继续往后指,所以只有在链表尾部添加结点时会受影响,其它函数不受任何影响。也会尽快补上这个不完美的地方。事实证明,链表初始化函数,插入函数、删除函数也受影响。

关于清空链表,按照理解来说,该从尾结点一个个删除比较符合理解习惯,但按照效率来讲,队列的那种从头结点删除效率更高,因为链表是单向的。两种方式我都实现且测试了,但更推荐队列的那种。

对于链表来说,目前这种是个人认为最通用的,最容易理解的,但不见得是最简单的,因为接口函数很多。写注释写到都快吐了,这应该是我写的最丰富的注释,因此容易理解。这还只是各基础,之后可能添加尾结点,将结点数据域改成结构体,实现双向链表。

按照C Primer Plus中的抽象数据类型ADT相关的名词:建立抽象,建立接口,实现接口,测试接口来定义标题。

建立抽象

在链表实现中,每个链节叫作结点,每个结点包含形成链表内容的信息和指向下一个结点的指针。结点结构的标记名为Node。链表结构的标记名为LinkedList,包含指向头结点结构的指针和标记链表项数的变量。

扫描二维码关注公众号,回复: 12660391 查看本文章

建立接口

#ifndef __LINKED_LIST_H__
#define __LINKED_LIST_H__

#include <stdbool.h>    /* 定义bool 类型 */
#include <stdio.h>      /* 定义输入输出 */
#include <stdint.h>     /* 定义常用数据类型 */
#include <stdlib.h>     /* 定义 malloc free exit */

#define DEBUG_OUTPUT    1

#define MAXQUEUE    10


typedef int32_t Item;


typedef uint32_t L_DATA_type;
typedef int32_t L_POSITION_type;
typedef uint16_t L_NUMBER_type;

/* 链表结点结构 */
typedef struct node
{
    Item item;
    struct node *next;
}Node;

typedef struct list
{
    Node* head;             /* 指向链表头的指针 */
    L_NUMBER_type items;         /* 链表中的项数 */
}LinkedList;





/**
 * 初始化链表
 * 前提条件:plist指向一个链表
 * 后置条件:链表被初始化为空
 */
void InitializeLinkedList(LinkedList* plist);

/**
 * 清空链表
 * 前提条件:plist指向被初始化的链表
 * 后置条件:队列被清空
 */
void EmptyTheLinkedList(LinkedList* plist);

/**
 * 检查链表是否已满
 * 前提条件:plist指向已初始化的链表
 * 后置条件:如果链表已满则返回true, 否则返回false
 */
bool LinkedListIsFull(const LinkedList* plist);

/**
 * 检查链表是否为空
 * 前提条件:plist指向被初始化的链表
 * 后置条件:如果链表为空则返回true, 否则返回false
 */
bool LinkedListIsEmpty(const LinkedList* plist);

/**
 * 确定链表中的项数
 * 前提条件:plist指向被初始化的链表
 * 后置条件:返回队列中的项数
 */
L_NUMBER_type LinkedListNodeCount(const LinkedList* plist);

/* 在链表尾部添加、删除结点 */

bool LinkedListAddNode(Item item, LinkedList* plist);

bool LinkedListDeleteNode(LinkedList* plist, Item* item);

/* 遍历链表来显示、 求和 */

void ShowLinkedListNode(const LinkedList* plist);

L_DATA_type GetLinkedListNodeSum(const LinkedList* plist);

/* 增(插入)、删、改、查 */

bool InsertNodeToLinkedList(LinkedList* plist, L_NUMBER_type position, Item item);

bool DeleteNodeFromLinkedList(LinkedList* plist, L_NUMBER_type position, Item* pitem);

bool ModifyNodeFromLinkedList(LinkedList* plist, L_NUMBER_type position, Item item);

L_POSITION_type SearchNodeFromLinkedList(LinkedList* plist, Item item);




#endif

实现接口

#include "LinkedList.h"

/* malloc 得到的 和 free释放的是什么? 得到的是一个指向新Node结点的指针, 释放的是指向新Node结点的指针 */
/*******************用于添加结点和删除结点************************/

static void CopyToNode(Item item, Node* pn);
static void CopyToItem(Node* pn, Item* pi);

/*********************显示结点数据域***********************/

static void ShowNodeItem(Item item);

/*********************用于链表值求和************************/

static void LinkedListValueSum(Item item);
static L_DATA_type GetLinkedListValueSum(void);
static void ClearLinkedListValueSum(void);

static void Traverse(const LinkedList* plist, void(*pfun)(Item item));
/**************************************************分界线***************************************************/

/**
 * CopyToNode
 * @brief   从结构体赋值到链表结点
 * @param   item 参数描述: 结构体指针
 * @param   pn 参数描述: 链表结点指针
 */
static void 
CopyToNode(Item item, Node* pn)
{
    pn->item = item;
}

/**
 * CopyToItem
 * @brief   从链表结点复制到结构体中
 * @param   pn 参数描述: 链表结点指针
 * @param   pi 参数描述: 结构体指针
 */
static void 
CopyToItem(Node* pn, Item* pi)
{
    *pi = pn->item;
}

static uint8_t term_val = 0;            ///< 变量:用于表示是第几个结点
/**
 * ShowNodeItem
 * @brief   显示队列结点数据域
 * @param   item 结点数据域
 */
static void 
ShowNodeItem(Item item)
{
    printf("node %d item is %d \n", term_val, item);
}


static L_DATA_type l_val_sum = 0;       ///< 变量:链表求和值保存
/**
 * LinkedListValueSum
 * @brief   对链表各项进行求和
 * @param   item 参数描述: 链表结点的数据域
 */
static void
LinkedListValueSum(Item item)
{
    l_val_sum += item;
}

/**
 * GetLinkedListValueSum
 * @brief   得到链表中的求和值
 * @retval  L_DATA_type 返回值描述: 求和值
 */
static L_DATA_type
GetLinkedListValueSum(void)
{
    return l_val_sum;
}

/**
 * ClearLinkedListValueSum
 * @brief   清除链表中的求和值
 */
static void
ClearLinkedListValueSum(void)
{
    l_val_sum = 0;
}

/**
 * Traverse
 * @brief   遍历链表,执行某种操作
 * @param   plist 参数描述: 链表指针
 * @param   pfun 参数描述: 函数指针
 * @note    若结点指针不是NULL 1.对当前结点执行回调函数,操作数据域  2.前进至下一个结点
 */
static void 
Traverse(const LinkedList* plist, void(*pfun)(Item item))
{
    Node *pnode = plist->head;

    while(pnode != NULL)
    {
        (*pfun)(pnode->item);   /* 对当前结点执行回调函数,操作数据域 */
        term_val++;             ///< 变量:用于show_node_item 函数
        pnode = pnode->next;    /* 前进至下一个结点 */
    }
#if DEBUG_OUTPUT
    if(term_val == 0)           /* 进入该函数时该变量值为0,若执行循环值非0,退出该函数时值清0 */
    {
        printf("LinkedList is Empty !, from Function: %s \n", __FUNCTION__);
    }
#endif
    term_val = 0;               ///< 变量:用于show_node_item 函数

}

/**************************************************分界线***************************************************/

/**
 * InitializeLinkedList
 * @brief   初始化链表
 * @param   plist 参数描述: 链表指针
 * @note    1.指针指向NULL 2.链表结点数为0
 */
void 
InitializeLinkedList(LinkedList* plist)
{
    plist->head = NULL;         /* 指针指向NULL */
    plist->items = 0;           /* 链表结点数为0 */
}

#if 0
/**
 * EmptyTheLinkedList
 * @brief   清空链表(从头结点开始删除)
 * @details 本函数清空链表是从开始处往尾部删除
 * @param   plist 参数描述: 链表指针
 * @note    1.保存下一个结点的地址 2.释放当前结点 3.前进至下一个结点 4.链表结点数减1
 */
void 
EmptyTheLinkedList(LinkedList* plist)
{
    Node* psave;
    while(! LinkedListIsEmpty(plist))     //while (plist->head != NULL)
    {
        psave = plist->head->next;      /* 保存下一个结点的地址 */
        free(plist->head);              /* 释放当前结点 */
        plist->head = psave;            /* 前进至下一个结点 */
        plist->items--;                 /* 链表结点数减1 */
    }
#if DEBUG_OUTPUT
    printf("LinkedList is Empty , from Function: %s \n", __FUNCTION__);
#endif
}
#elif 1
/**
 * EmptyTheLinkedList
 * @brief   清空链表(从尾结点开始删除)
 * @details 每删除一个尾结点发生一次变化
 * @param   plist 参数描述: 链表指针
 * @note    当链表不为空:删除尾结点
 * @remarks 涉及到几个函数嵌套,而且对于只有指向头结点没有指向尾结点的来说,从头结点删除效率更高
 */
void
EmptyTheLinkedList(LinkedList* plist)
{
    Item temp_item;
    while (! LinkedListIsEmpty(plist))
    {
        LinkedListDeleteNode(plist, &temp_item);
    }
#if DEBUG_OUTPUT
    printf("LinkedList is Empty , from Function: %s \n", __FUNCTION__);
#endif
}
#endif

/**
 * LinkedListIsFull
 * @brief   链表是否为满
 * @param   plist 参数描述: 链表首指针
 * @retval  true 返回值描述: 链表为满
 * @retval  false 返回值描述: 链表非满
 * @note    1.链表实际结点数与限定链表为满时结点数的判断
 */
bool 
LinkedListIsFull(const LinkedList* plist)
{
    return plist->items == MAXQUEUE;
}

/**
 * LinkedListIsEmpty
 * @brief   链表是否为空
 * @param   plist 参数描述: 链表指针
 * @retval  true 返回值描述: 链表为空
 * @retval  false 返回值描述: 链表非空
 * @note    1.链表实际结点数与空链表时结点数的判断
 */
bool 
LinkedListIsEmpty(const LinkedList* plist)
{
    return plist->items == 0;
}


/**
 * AddItem
 * @brief   添加到链表尾部
 * @param   item 参数描述: 
 * @param   plist 参数描述: 无
 * @retval  true 返回值描述: 无
 * @retval  false 返回值描述: 无
 */
bool LinkedListAddNode(Item item, LinkedList* plist)
{
    L_POSITION_type temp_index;

    temp_index = LinkedListNodeCount(plist);                        /* 获取链表中结点数 */
    if (! InsertNodeToLinkedList(plist, temp_index, item))          /* 插入到链表尾部 */
    {
        return false;   
    }else
    {
        return true;
    }
}

/**
 * DeleteItem
 * @brief   从链表尾结点删除一项
 * @param   plist 参数描述: 链表指针
 * @param   item 参数描述: 被删除结点的数据域
 * @retval  true 返回值描述: 删除成功
 * @retval  false 返回值描述: 删除失败
 * @note    1.获取链表中结点数 2.删除尾结点
 */
bool 
LinkedListDeleteNode(LinkedList* plist, Item* pitem)
{
    L_POSITION_type temp_index;

    temp_index = LinkedListNodeCount(plist);                        /* 获取链表中结点数 */
    if (! DeleteNodeFromLinkedList(plist, temp_index - 1, pitem))    /* 删除尾结点 */
    {
        return false;   
    }else
    {
        return true;
    }
}

/**
 * LinkedListNodeCount
 * @brief   查询链表中项的数目
 * @param   plist 参数描述: 链表指针
 * @retval  L_NUMBER_type 返回值描述: 项的数目
 */
L_NUMBER_type 
LinkedListNodeCount(const LinkedList* plist)
{
    return plist->items;
}


/**
 * ShowQueueNode
 * @brief   显示队列数据
 * @param   pq 队列指针
 */
void 
ShowLinkedListNode(const LinkedList* plist)
{
    Traverse(plist, ShowNodeItem);
}


/**
 * GetLinkedListNodeSum
 * @brief   得到链表数据和
 * @param   plist 参数描述: 链表指针
 * @retval  L_DATA_type 返回值描述: 链表数据和
 * @note    1.遍历链表求和 2.获取数据和用于返回值 3.清除求和变量
 */
L_DATA_type
GetLinkedListNodeSum(const LinkedList* plist)
{
    L_DATA_type sum;

    Traverse(plist, LinkedListValueSum);        /* 遍历链表求和 */
    sum = GetLinkedListValueSum();              /* 获取数据和用于返回值 */
    ClearLinkedListValueSum();                  /* 清除求和变量 */

    return sum;
}


/**
 * InsertNodeToLinkedList
 * @brief   
 * @param   plist 参数描述: 链表指针
 * @param   position 参数描述: 位置,取值范围: 0~plist->items
 * @param   item 参数描述: 结点数据域
 * @retval  true 返回值描述: 插入成功
 * @retval  false 返回值描述: 插入失败
 * @note    1. 若位置不可能插入到当前链表中,返回失败
 * @note    2. 若位置为0,创建一个结点,将数据域写入,该结点指向首结点,该结点成为新的首结点,链表结点数加1,返回成功
 * @note    3. 若为空链表,返回失败,否则 在要插入位置前一个结点停止,创建一个结点,将数据域写入,该结点指向位置前一个结点指向的结点,该结点成为对应位置处的结点,链表结点数加1,返回成功
 */
bool InsertNodeToLinkedList(LinkedList* plist, L_NUMBER_type position, Item item)
{
    Node* pnode = plist->head;

    if(position > plist->items)                             /* 等于plist->items时表示插入到链表尾部 */
    {
        return false;                                       /* 若位置不可能插入到当前链表中,返回失败 */
    }else if(position == 0)
    {
        Node* pnew = (Node*)malloc(sizeof(Node));           /* 创建一个结点 */
        CopyToNode(item, pnew);                             /* 将数据域写入 */
        pnew->next = pnode;                                 /* 该结点指向首结点 */
        plist->head = pnew;                                 /* 该结点成为新的首结点 */
        plist->items++;                                     /* 链表结点数加1 */

        return true;                                        /* 返回成功 */
    }else
    {
        if(pnode == NULL)
        {
            return false;                                   /* 若为空链表,返回失败 */
        }else
        {
            for(L_NUMBER_type i = 0; i < position-1; i++)        /* 在要插入位置前一个结点停止 */
            {
                pnode = pnode->next;
            }

            Node* pnew = (Node*)malloc(sizeof(Node));       /* 创建一个结点 */
            CopyToNode(item, pnew);                         /* 将数据域写入 */
            pnew->next = pnode->next;                       /* 该结点指向位置前一个结点指向的结点 */
            pnode->next = pnew;                             /* 该结点成为对应位置处的结点 */
            plist->items++;                                 /* 链表结点数加1 */

            return true;                                    /* 返回成功 */
        }
    }
}

/**
 * DeleteNodeFromLinkedList
 * @brief   删除链表结点
 * @param   plist 参数描述: 链表指针
 * @param   position 参数描述: 位置,取值范围: 0~plist->items - 1
 * @param   pitem 参数描述: 删除结点的数据域
 * @retval  true 返回值描述: 删除成功
 * @retval  false 返回值描述: 删除失败
 * @note    1.位置为0:判断是否是空链表:是则返回失败,否则将修改链表 首结点前进到下一个结点,链表结点数减1
 * @note    2.位置不在当前链表内,返回失败
 * @note    3.在要删除位置前一个结点停止,将要删除的位置赋给结点指针,待删除结点的数据域通过指针返回,将删除位置前一个结点的指向删除位置后一个结点,链表结点数减1
 */
bool DeleteNodeFromLinkedList(LinkedList* plist, L_NUMBER_type position, Item* pitem)
{
    Node* pnode = plist->head;

    if(position == 0)
    {
        if(pnode == NULL)
        {
            return false;                           /* 是空链表,返回失败 */
        }else
        {
            plist->head = pnode->next;              /* 首结点前进到下一个结点 */
            plist->items--;                         /* 链表结点数减1 */

            return true;
        }
    }else if(position >= plist->items)
    {
        return false;                               /* 位置不在当前链表内,返回失败 */
    }else
    {
        for(L_NUMBER_type i = 0; i < position-1; i++)    /* 在要删除位置前一个结点停止 */
        {
            pnode = pnode->next;
        }

        Node* pn = pnode->next;                     /* 将要删除的位置赋给结点指针 */
        CopyToItem(pn, pitem);                      /* 待删除结点的数据域通过指针返回 */
        pnode->next = pn->next;                     /* 将删除位置前一个结点的指向删除位置后一个结点 */
        plist->items--;                             /* 链表结点数减1 */

        pn = NULL;

        return true;
    }
}

/**
 * ModifyNodeFromLinkedList
 * @brief   修改链表中特定位置结点的数据域
 * @param   plist 参数描述: 链表指针
 * @param   position 参数描述: 位置,取值范围:0~plist->items - 1
 * @param   item 参数描述: 结点数据域
 * @retval  true 返回值描述: 修改成功
 * @retval  false 返回值描述: 修改失败
 * @note    1. 位置已不在当前链表内,返回失败 2.当前为空链表,返回失败 3.找到对应位置,修改数据域,返回成功
 */
bool ModifyNodeFromLinkedList(LinkedList* plist, L_NUMBER_type position, Item item)
{
    Node* pnode = plist->head;

    if(position >= plist->items)    
    {
        return false;                                   /* 位置已不在当前链表内,返回失败 */
    }

    if(pnode == NULL)
    {
        return false;                                   /* 当前为空链表,返回失败 */
    }else
    {
        for(L_NUMBER_type i = 0; i <= position-1; i++)       /* 找到对应位置 */
        {
            pnode = pnode->next;
        }

        pnode->item = item;                             /* 修改数据域 */

        return true;                                    /* 返回成功 */
    }
}

/**
 * SearchNodeFromLinkedList
 * @brief   对链表结点逐个判断,查找item所在位置
 * @param   plist 参数描述: 链表指针
 * @param   item 参数描述: 结点数据域
 * @retval  int16_t 返回值描述: -1,表示没有找到,其它,表示在链表中的位置(从0开始)
 * @note    1.当指向链表结点的指针不是NULL:链表数据域进行判断:成功则返回位置,失败则前进至下一个结点,结点位置加1 2.链表已遍历完
 */
L_POSITION_type SearchNodeFromLinkedList(LinkedList* plist, Item item)
{
    Node* pnode = plist->head;
    L_POSITION_type temp_position = 0;

    while(pnode != NULL)                /* 当指向链表结点的指针不是NULL */
    {
        if(pnode->item == item)         /* 链表数据域进行判断 */
        {
            return temp_position;
        }else
        {
            pnode = pnode->next;        /* 前进至下一个结点 */
            temp_position++;            /* 结点位置加1 */
        }
    }

    return -1;   // -1,表示没有找到    /* 链表已遍历完 */
}

测试接口---测试结果

插入到头结点和尾节点

删除尾结点和头结点

修改尾结点和头结点

查找尾结点和头结点的数据,对链表结点求和取平均

清空链表,打印链表

因为测试清空链表的从尾结点开始清除,重新测试了一下

测试接口---代码实现

虽然测试接口交互性做得还不怎么样,但绝对把所有函数,所有特殊情况都试了

测试代码逻辑

测试代码

#include <stdio.h>      /* 调用printf 函数 */
#include <time.h>       /* 调用time 函数 */
#include <stdlib.h>     /* 调用srand rand 函数 */
#include "LinkedList.h" /* 调用LinkedList的数据类型和操作函数 */


#define DEBUG_OUTPUT    1


int main(void)
{
    LinkedList line;
    Item temp_item;

    srand((unsigned)time(NULL));
    InitializeLinkedList(&line);

    for(uint8_t i=0; i<5; i++)
    {
        if(! LinkedListIsFull(&line))
        {
            temp_item = rand() % 256;
#if DEBUG_OUTPUT 
            printf("random_val is:  %d \n", temp_item);
#endif
            LinkedListAddNode(temp_item, &line);            
        }else
        {
            ShowLinkedListNode(&line);
            
            L_DATA_type sum = GetLinkedListNodeSum(&line);
            printf("\n LinkedList sum is %d, average value is:  %d \n\n",sum, sum/MAXQUEUE);
            
            break;
        }
    }
    ShowLinkedListNode(&line);

    printf("*********START insert linkedList to head node*********** \n");
    temp_item = rand()%256;
    printf("random_val is:  %d \n", temp_item);
    if (! InsertNodeToLinkedList(&line, 0, temp_item))
    {
        printf("insert to linkedList error ! \n");
    }

    ShowLinkedListNode(&line);
    uint16_t temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH inserted linkedList num is:  %d*********** \n\n", temp_index);


    printf("*********START insert linkedList to tail node*********** \n");
    temp_item = rand()%256;
    printf("random_val is:  %d \n", temp_item);
    if (! InsertNodeToLinkedList(&line, temp_index, temp_item))
    {
        printf("insert to linkedList error ! \n");
    }

    ShowLinkedListNode(&line);
    temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH inserted linkedList num is:  %d*********** \n\n", temp_index);



    printf("*********START delete tail node from linkedList*********** \n");
    if (! DeleteNodeFromLinkedList(&line, temp_index - 1, &temp_item))
    {
        printf("delete item from linkedList error! \n");
    }
    
    ShowLinkedListNode(&line);
    temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH deleted linkedList num is:  %d*********** \n\n", temp_index);



    printf("*********START delete head node from linkedList*********** \n");
    if (! DeleteNodeFromLinkedList(&line, 0, &temp_item))
    {
        printf("delete item from linkedList error! \n");
    }
    
    ShowLinkedListNode(&line);
    temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH deleted linkedList num is:  %d*********** \n\n", temp_index);


    printf("*********START modify tail node from linkedList*********** \n");
    temp_item = rand()%256;
    Item temp_tail_item = temp_item;
    printf("random_val is:  %d \n", temp_item);
    if (! ModifyNodeFromLinkedList(&line, temp_index-1, temp_item))
    {
        printf("modify item from linkedList error! \n");
    }
    ShowLinkedListNode(&line);
    temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH modified linkedList num is:  %d*********** \n\n", temp_index);



    printf("*********START modify head node from linkedList*********** \n");
    temp_item = rand()%256;
    printf("random_val is:  %d \n", temp_item);
    if (! ModifyNodeFromLinkedList(&line, 0, temp_item))
    {
        printf("modify item from linkedList error! \n");
    }
    ShowLinkedListNode(&line);
    temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH modified linkedList num is:  %d*********** \n\n", temp_index);


    printf("*********START search from linkedList*********** \n");
    printf("temp_tail_item is: %d \n", temp_tail_item);
    int16_t temp_search_index = SearchNodeFromLinkedList(&line, temp_tail_item);
    if(temp_search_index == -1)
    {
        printf("search item from linkedList error! \n");
    }else
    {
        printf("the position of linkeList is: %d \n", temp_search_index);
    }
    ShowLinkedListNode(&line);
    temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH searched linkedList num is:  %d*********** \n\n", temp_index);



    printf("*********START search from linkedList*********** \n");
    printf("temp_item is: %d \n", temp_item);
    temp_search_index = SearchNodeFromLinkedList(&line, temp_item);
    if(temp_search_index == -1)
    {
        printf("search item from linkedList error! \n");
    }else
    {
        printf("the position of linkeList is: %d \n", temp_search_index);
    }
    ShowLinkedListNode(&line);
    temp_index = LinkedListNodeCount(&line);
    printf("*********FINISH searched linkedList num is:  %d*********** \n\n", temp_index);

    L_DATA_type sum = GetLinkedListNodeSum(&line);
    printf("\n LinkedList sum is %d, average value is:  %d \n\n",sum, sum/MAXQUEUE);

    EmptyTheLinkedList(&line);      /* 若链表清空后会有打印 */

    ShowLinkedListNode(&line);      /* 若链表为空会有打印 */

    return 0;
}


猜你喜欢

转载自blog.csdn.net/quanquanxiaobu/article/details/112669198