使用容器操作单链表并测试

1 单链表的实现

首先是一个最简单的单链表的实现,结构体中存着的是下一个结构体的指针

数据结构如下

typedef struct linked_item
{
    struct linked_item *next; //next element in list, or NULL
}linked_item_t;

typedef linked_item_t * linked_list_t;

下面编写单链表的操作函数:

1.1首先是判断链表是否为空的函数

/**
 *test if list is empty
 *list is empty when return 1, otherwise list is not empty
 */
int list_is_empty(linked_list_t* list)
{
    return (list == (void*)0);
}
  • 在这里传入的参数应该是一个指针
    例如我定义了一个 linked_list_t testlist = NULL;
    则传入list_is_empty(&testlist);
  • 另外,你知道吗,&testlist->next 是等于 testlist指针的。
    先从linked_list_t testlist开始分析,它等价于linked_item_t * testlist
    testlist 指向的就是一个linked_item的结构体
    如果我对testlist取地址得到的也是一个指向linked_item结构体的指针且这个结构体的next成员就是testlist

想明白这点事继续看下去的基础,如果没想明白可以动手试试看。

1.2 取链表结尾项的函数

/*
 *linked_list_get_last_item
 *list is the head pointer
 */
linked_item_t* linked_list_get_last_item(linked_list_t* list)
{
    linked_item_t* last_item = NULL;
    linked_item_t* it;
    for (it = *list; it->next; it = it->next)
        last_item = it->next;
        // or  for(it = *list; it; it = it->next)
        //         if(it) last_item = it;
    return last_item;
}

从头结点开始循环遍历链表,每次将遍历的节点存入last_item,知道遇到NULL,表示已经到了结尾
此时返回last_item

1.3 链表节点添加函数

/*
 *linked_list_add
 *list is the head pointer
 *确定了两个绑定参数,一个是list他是整个链表的起点 list->next = *list
 */
void linked_list_add(linked_list_t* list, linked_item_t* item)
{
    //check if item is already in list
    linked_item_t* it;
    for (it = *list; it; it = it->next)
    {
        if (it == item) return;
    }

    //add first, *list represent head pointer;
    item->next = *list;
    *list = item;      //at this time, head pointer is add_in item
}

首先判断待添加的节点是否已经在链表中,如果已经在链表中,那么就返回,什么也不做
否则将待添加的节点添加到头节点,并将头节点设为这个添加完的节点

1.4 添加到结尾的函数

/*
 *linked_list_add_tail
 *list is the head pointer
 */
void linked_list_add_tail(linked_list_t* list, linked_item_t* item)
{
    //linked_item_t* last_item = linked_list_get_last_item(list);
    //check if item is already in list
    linked_item_t* it;
    for (it = *list; it->next; it = it->next)
    {
        if (it == item) return;
    }

    item->next = NULL;
    it->next = item;
}

首先判断待添加的节点是否已经在链表中,如果已经在链表中,那么就返回,什么也不做
否则,这时候it已经遍历到了链表的结尾,这时候只需要把待添加的节点添加到结尾就可以,在这之前需要将待添加的节点的下一个节点设为NULL

1.5节点移除函数

/**
 * Remove data_source from run loop
 * return -1 represent remove fail
 * @note: assumes that data_source_t.next is first element in data_source
 */
int  linked_list_remove(linked_list_t * list, linked_item_t *item)
{    
    // <-- remove item from list
    if (!item) return -1;
    linked_item_t* it;
    for (it = *list; it; it = it->next)
    {
        if (it->next == item)
        {
            it->next = item->next;
            return 0;
        }
    }

    //when not return in for_loop, return -1 
    return -1;
}

移除流程是这样的:
如果item是一个空指针,返回-1表示移除失败
如果在链表中遍历到了这个节点,那么就将这个节点移除
移除的方法是将这个节点上一个节点的下一个节点链接到要移除的节点的下一个节点

1.6最后就是节点计数函数(统计节点中)

/**
* @returns number of items in list
*/
int linked_list_count(linked_list_t* list)
{
    linked_item_t *it;
    int count = 0;
    for (it = *list; it; it = it->next) ++count;
    return count;
}

2 编写容器操作单链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值