您的位置:首页 > 其它

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

2017-01-09 10:28 309 查看

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 编写容器操作单链表

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: