单向链表C语言实现详解

目录

一、单向链表数据结构

二、单向链表增删改查函数声明

三、创建链表

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 作用为清空链表数据缓存区链表头部数据

 

三、创建链表

1、链表头部动态创建

/**
 * 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;
}

2、链表头部静态创建

/**
 * 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;
}

四、节点添加

1、 头插法

每次添加节点都是在头节点前面添加,node1为最新添加的节点,添加过程

① 动态创建一个新的节点node

② node->next = list->head

③ list->head = node

单向链表C语言实现详解_第1张图片

/**
 * 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;
}

2、 尾插法

每次添加节点都是在后继节点为NULL的节点后面添加,头节点始终不动指向链表第一个节点,node1为最新添加的节点,添加过程为:

① 动态创建一个新的节点node,node->next = NULL

② 找到后继节点为NULL的尾节点tail

③ tail->next = node

 

单向链表C语言实现详解_第2张图片

/**
 * 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;
}

3、 位置节点前或后插入

节点前添加过程为:

① 找到 pos 节点的前驱节点 prev(node2)

② new->next = pos

③ prev->next = new

节点后添加过程为:

① new->next = pos->next

② pos->next = new

单向链表C语言实现详解_第3张图片

注意:在位置节点前插入中如果位置节点为链表头节点,则需要向前移动头节点指向新插入节点。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节点空间

单向链表C语言实现详解_第4张图片

注意:如果要删除节点为链表头节点,则需要向后移动头结点。警惕指针丢失和内存泄漏。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);
}

 

 

 

 

 

 

 

 

你可能感兴趣的:(数据结构与算法)