目录
一、单向链表数据结构
二、单向链表增删改查函数声明
三、创建链表
1、链表头部动态创建
2、链表头部静态创建
四、节点添加
1、 头插法
2、 尾插法
3、 位置节点前或后插入
五、节点删除
六、链表清空
七、链表销毁
八、验证程序
struct singal_list_node
{
struct singal_list_node *next; /* next node*/
void *value; /* node value */
};
struct single_list
{
struct singal_list_node *head; /* list head */
unsigned int len; /* node num */
};
单向链表每一个节点只有一个后继节点,只能由前一节点向后查找后继节点,而不能由当前节点查找到它的前驱节点。在使用时,需要先动态创建一个头节点 list,并将 list-head 指向链表中的第一个节点,同时记录链表中节点数目
extern struct single_list* single_list_creat(void);
extern int single_list_add_node_head(struct single_list *list, void *value);
extern int single_list_add_node_tail(struct single_list *list, void *value);
extern int single_list_insert_node (struct single_list *list, struct singal_list_node *pos_node, void *value, char dir);
extern int single_list_node_del (struct single_list *list, struct singal_list_node *del_node, char val_isdyn);
extern int single_list_node_empty (struct single_list *list, char val_isdyn);
extern int single_list_destroy (struct single_list *list, char val_isdyn);
extern void single_list_test(void);
说明:
1、single_list_creat 动态创建一个单项链表,包括链表头和链表数据空间,与single_list_destroy配对使用
2、single_list_init 初始化一个单项链表,链表头为静态创建的,与single_list_node_empty配对使用
3、single_list_node_empty 作用为清空链表数据缓存区,保留链表头部结构
4、single_list_destroy 作用为清空链表数据缓存区链表头部数据
/**
* dynamically create a single list.
*
* @return NULL:malloc fail
* !NULL:success
*/
struct single_list* single_list_creat(void)
{
struct single_list *list = NULL;
list = SINGAL_LIST_MALLOC(sizeof(*list));
if (list == NULL)
return NULL;
list->head = NULL;
list->len = 0;
return list;
}
/**
* init a single list.
*
* @param list: single list
* @return -1:list is null
* 0:success
*/
int single_list_init(struct single_list *list)
{
if (list == NULL)
return -1;
list->head = NULL;
list->len = 0;
return 0;
}
每次添加节点都是在头节点前面添加,node1为最新添加的节点,添加过程
① 动态创建一个新的节点node
② node->next = list->head
③ list->head = node
/**
* insert a value to the single list forward.
*
* @param list: single list
* @param value: data
* @return -1:list is null or value is null
* -2:node malloc fail
* 0:success
*/
int single_list_add_node_head(struct single_list *list, void *value)
{
struct singal_list_node *node = NULL;
if (list == NULL || value == NULL)
return -1;
node = SINGAL_LIST_MALLOC(sizeof(*node));
if (node == NULL)
return -2;
/* add node */
node->value = value;
node->next = list->head;
/* move list head to first node */
list->head = node;
list->len++;
return 0;
}
每次添加节点都是在后继节点为NULL的节点后面添加,头节点始终不动指向链表第一个节点,node1为最新添加的节点,添加过程为:
① 动态创建一个新的节点node,node->next = NULL
② 找到后继节点为NULL的尾节点tail
③ tail->next = node
/**
* insert a value to the single list backwards.
*
* @param list: single list
* @param value: data
* @return -1:list is null or value is null
* -2:node malloc fail
* 0:success
*/
int single_list_add_node_tail(struct single_list *list, void *value)
{
struct singal_list_node *node = NULL;
struct singal_list_node *tail = NULL;
if (list == NULL || value == NULL)
return -1;
node = SINGAL_LIST_MALLOC(sizeof(*node));
if (node == NULL)
return -2;
node->value = value;
node->next = NULL;
/* first node */
if (list->head == NULL && list->len == 0)
list->head = node;
/* not the first node */
else
{
tail = list->head;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = node;
}
list->len++;
return 0;
}
节点前添加过程为:
① 找到 pos 节点的前驱节点 prev(node2)
② new->next = pos
③ prev->next = new
节点后添加过程为:
① new->next = pos->next
② pos->next = new
注意:在位置节点前插入中如果位置节点为链表头节点,则需要向前移动头节点指向新插入节点。new->next = list->head, list->head = new
/**
* Insert a new node before or after a node.
*
* @param list: single list
* @param pos_node: insert node postion
* @param value: data
* @param dir: 1 before, 2 after
* @return -1:list is null or value is null
* -2:node malloc fail
* -3:pos node is not in the list
* 0:success
*/
int single_list_insert_node(struct single_list *list, struct singal_list_node *pos_node, void *value, char dir)
{
struct singal_list_node *node = NULL;
struct singal_list_node *prev = NULL;
if (list == NULL || pos_node == NULL || value == NULL)
return -1;
node = SINGAL_LIST_MALLOC(sizeof(*node));
if (node == NULL)
return -2;
node->value = value;
node->next = NULL;
/* Insert before the node*/
if (dir == 1)
{
/* before the head */
if (pos_node == list->head)
{
node->next = list->head;
list->head = node;
}
else
{
prev = list->head;
while (pos_node != prev->next)
{
prev = prev->next;
if (prev == NULL) /* pos node is not in the list */
return -3;
}
node->next = pos_node;
prev->next = node;
}
}
/* insert after the node */
else if (dir == 2)
{
node->next = pos_node->next;
pos_node->next = node;
}
list->len++;
return 0;
}
节点删除过程为:
① 找到del节点的前驱节点 prev(node2)
② prev->next = del->next
③ 释放del节点空间
注意:如果要删除节点为链表头节点,则需要向后移动头结点。警惕指针丢失和内存泄漏。list->head = del->next,然后再释放del节点空间
/**
* delete a node.
* @note The value space may be static, so the val_isdyn identification is needed
* to tell if the value space needs to be released manually
* @param list: single list
* @param val_isdyn: 1 = value is dynamic apply
* @return -1:list is null
* -2:delete node is not in the list
* 0:success
*/
int single_list_node_del(struct single_list *list, struct singal_list_node *del_node, char val_isdyn)
{
struct singal_list_node *prev = NULL;
struct singal_list_node *cur = NULL;
if (list == NULL || del_node == NULL)
return -1;
cur = list->head;
while (cur != NULL && cur != del_node)
{
prev = cur;
cur = cur->next;
}
/* delete node is not in the list */
if (cur == NULL)
return -2;
/* delete node is the head node */
if (cur == list->head)
list->head = cur->next;
else
prev->next = cur->next;
cur->next = NULL;
if (val_isdyn)
{
SINGAL_LIST_FREE(cur->value);
}
SINGAL_LIST_FREE(cur);
cur = NULL;
list->len--;
return 0;
}
/**
* empty the single list all node.
* @note The value space may be static, so the val_isdyn identification is needed
* to tell if the value space needs to be released manually
* @param list: single list
* @param val_isdyn: 1 = value is dynamic apply
* @return -1:list is null
* 0:success
*/
int single_list_node_empty(struct single_list *list, char val_isdyn)
{
struct singal_list_node *node = NULL;
if (list == NULL)
return -1;
while (list->head != NULL && list->len > 0)
{
/* move list head node to head next node */
node = list->head;
list->head = list->head->next;
list->len--;
if (val_isdyn)
{
SINGAL_LIST_FREE(node->value);
node->value = NULL;
}
/* free space */
node->next = NULL;
SINGAL_LIST_FREE(node);
node = NULL;
}
return 0;
}
/**
* destroy the single list.
* @note The list node needs to be empty before destroy list
* @param list: single list
* @return -1:list is null
* 0:success
*/
int single_list_destroy(struct single_list *list, char val_isdyn)
{
if (single_list_node_empty(list, val_isdyn) != 0)
return -1;
list->head = NULL;
SINGAL_LIST_FREE(list);
list = NULL;
return 0;
}
struct single_list *single_list;
struct singal_list_node *single_node;
int single_test_w[] = {10, 20, 30, 40, 50};
int single_test_r[15] = {0};
void single_list_test(void)
{
int i = 0;
single_list = single_list_creat();
/* head insert */
single_list_add_node_head(single_list, (void*)&single_test_w[0]);
single_list_add_node_head(single_list, (void*)&single_test_w[1]);
single_list_add_node_head(single_list, (void*)&single_test_w[2]);
single_list_add_node_head(single_list, (void*)&single_test_w[3]);
single_list_add_node_head(single_list, (void*)&single_test_w[4]);
single_node = single_list->head;
for (i=0; ilen; i++)
{
single_test_r[i] = *(int*)single_node->value;//50 40 30 20 10
single_node = single_node->next;
}
/* tail insert */
single_list_node_empty(single_list, 0);
single_list_add_node_tail(single_list, (void*)&single_test_w[0]);
single_list_add_node_tail(single_list, (void*)&single_test_w[1]);
single_list_add_node_tail(single_list, (void*)&single_test_w[2]);
single_list_add_node_tail(single_list, (void*)&single_test_w[3]);
single_list_add_node_tail(single_list, (void*)&single_test_w[4]);
single_node = single_list->head;
for (i=0; ilen; i++)
{
single_test_r[i] = *(int*)single_node->value;//10 20 30 40 50
single_node = single_node->next;
}
/* pos insert */
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[0], 1);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[1], 1);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[2], 1);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[3], 1);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[4], 1);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[0], 2);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[1], 2);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[2], 2);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[3], 2);
single_list_insert_node(single_list, single_list->head, (void*)&single_test_w[4], 2);
single_node = single_list->head;
for (i=0; ilen; i++)
{
single_test_r[i] = *(int*)single_node->value;
single_node = single_node->next;
}
/* destroy list */
single_list_destroy(single_list, 0);
}