C数据结构-线性表之单链表

来源:互联网 发布:吴京票房号召力知乎 编辑:程序博客网 时间:2024/05/15 01:36

线性表之单链表

单链表的设计之初,笔者在考虑一个首要的问题,就是单链表的节点是在插入的函数内部创建,还是在函数外部创建。考虑到用户在插入的时候,变量生命周期的不确定性以及容易造成内存泄漏等问题,综合考虑之下使用了内部创建节点的方式。笔者设计的单链表中包含了单链表的反转和合并等有趣的操作,其中的奥妙如果读者有兴趣可以细究。比如为什么笔者使用了二级指针来合并单链表,而不直接使用一级指针,比如为什么在清空链表节点时,根据length清空会有可能会发生内存泄漏....等等。下面是代码:

#ifndef LINKEDLIST_H#define LINKEDLIST_H#ifndef NULL#define NULL 0#endif/* 元素类型 */typedef int elem_t;/* 节点结构体 */typedef struct _tag_linked_list_node{    elem_t data;    struct _tag_linked_list_node *next;}ll_node;/* 链表结构体 */typedef struct _tag_linked_list{    ll_node head;   /* 哑结点 */    int length;     /* 链表长度 */}linked_list;/** * 创建链表 * @return  返回链表指针,NULL表示创建失败 */linked_list *linked_list_create();/** * 从头部插入元素 * @param plist 链表指针 * @param pe    被插入元素的指针 * @return      1:成功 0:失败 */int linked_list_insert(linked_list *plist,elem_t *pe);/** * 从尾部插入元素 * @param plist 链表指针 * @param pe    被插入元素的指针 * @return      1:成功 0:失败 */int linked_list_append(linked_list *plist,elem_t *pe);/** * 查找元素 * @param plist 链表指针 * @param i     元素位置索引 * @param pe    用于保存被查找元素的值的指针 * @return      1:成功 0:失败 */int linked_list_get(linked_list *plist,int i,elem_t *pe);/** * 按索引删除元素 * @param plist 链表指针 * @param i     被删除元素的索引 * @param pe    用于保存被删除元素的值的指针 * @return      1:成功 0:失败 */int linked_list_remove(linked_list *plist,int i,elem_t *pe);/** * 链表反转 * @param plist 链表指针 * @return 1:成功 0:失败 */int linked_list_reverse(linked_list *plist);/** * 链表合并,将第二个链表链接到第一个链表,第二个链表指针置空 * @param dest 合并的目标链表 * @param pp_src 被合并的链表的指针的指针 * @return 返回合并后的链表的指针(第一个参数) */linked_list *linked_list_merge(linked_list *dest,linked_list **pp_src);/** * 清空链表 * @param plist 链表指针 * @return      1:成功 0:失败 */int linked_list_clear(linked_list *plist);/** * 销毁链表 * @param plist 链表指针 * @return      1:成功 0:失败 */int linked_list_destroy(linked_list *plist);#endif // LINKEDLIST_H

#include "LinkedList.h"#include <malloc.h>/** * 创建链表 * @return  返回链表指针,NULL表示创建失败 */linked_list *linked_list_create(){    linked_list *plist = (linked_list *)malloc(sizeof(linked_list));    if(plist != NULL)    {        plist->length = 0;        plist->head.next = NULL;    }    return plist;}/** * 从头部插入元素 * @param plist 链表指针 * @param pe    被插入元素的指针 * @return      1:成功 0:失败 */int linked_list_insert(linked_list *plist,elem_t *pe){    int ret = ( (plist != NULL) && (pe != NULL));    if(ret)    {        ll_node *node = (ll_node *)malloc(sizeof(ll_node));        ll_node *head = &(plist->head);        if(node != NULL)        {            node->next = head->next;            head->next = node;            node->data = *pe;            plist->length++;        }        else        {            ret = 0;        }    }    return ret;}/** * 从尾部插入元素 * @param plist 链表指针 * @param pe    被插入元素的指针 * @return      1:成功 0:失败 */int linked_list_append(linked_list *plist,elem_t *pe){    int ret = ( (plist != NULL) && (pe != NULL));    if(ret)    {        ll_node *node = (ll_node *)malloc(sizeof(ll_node));        if(node != NULL)        {            int pos = 0;            ll_node *current = &(plist->head);            /* 移动到尾部 */            for(pos = 0;pos < plist->length;pos++)            {                current = current->next;            }            node->next = NULL;            node->data = *pe;            current->next = node;            plist->length++;        }        else        {            ret = 0;        }    }    return ret;}/** * 查找元素 * @param plist 链表指针 * @param i     元素位置索引 * @param pe    用于保存被查找元素的值的指针 * @return      1:成功 0:失败 */int linked_list_get(linked_list *plist,int i,elem_t *pe){    int ret = ( (plist != NULL) && (pe != NULL)  && (i >= 0) && (i < plist->length));    if(ret)    {        int pos = 0;        ll_node *current = plist->head.next;        /* 移动到尾部 */        for(pos = 0;pos < i;pos++)        {            current = current->next;        }        *pe = current->data;    }    return ret;}/** * 按索引删除元素 * @param plist 链表指针 * @param i     被删除元素的索引 * @param pe    用于保存被删除元素的值的指针 * @return      1:成功 0:失败 */int linked_list_remove(linked_list *plist,int i,elem_t *pe){    int ret = ( (plist != NULL) && (pe != NULL) && (i >= 0) && (i < plist->length));    if(ret)    {        int pos = 0;        ll_node *pre = &(plist->head);        for(pos = 0;pos < i;pos++)        {            pre = pre->next;        }        /* 保存要被删除的元素的值 */        *pe = pre->next->data;        pre->next = pre->next->next;        plist->length--;    }    return ret;}/** * 链表反转 * @param plist 链表指针 * @return 1:成功 0:失败 */int linked_list_reverse(linked_list *plist){    int ret = (plist != NULL);    if(ret)    {        if(plist->length > 1)        {            int i;            /* 保存尾元素的指针 */            ll_node *tail = &(plist->head);            for(i = 0;i < plist->length;i++)            {                tail = tail->next;            }            /* 将头元素的位置调整到原尾元素的后部插入 */            while(plist->head.next != tail)            {                /* 保存头部元素的指针 */                ll_node *old_head = plist->head.next;                /* 调整头结点指针的位置,指向原头部的下一个元素 */                plist->head.next = old_head->next;                /* 将保存的原头部元素插入到原尾部元素的后面 */                old_head->next = tail->next;                tail->next = old_head;            }        }    }    return ret;}/** * 链表合并,将第二个链表链接到第一个链表,第二个链表指针置空 * @param dest 合并的目标链表 * @param pp_src 被合并的链表的指针的指针 * @return 返回合并后的链表的指针(第一个参数) */linked_list *linked_list_merge(linked_list *dest,linked_list **pp_src){    if((dest != NULL) && ( (*pp_src) != NULL) && ((*pp_src)->length != 0))    {        int i;        ll_node *current = &(dest->head);        /* 移动到目标链表的尾部元素 */        for(i = 0;i < dest->length;i++)        {            current = current->next;        }        current->next = (*pp_src)->head.next;        dest->length += (*pp_src)->length;        free(*pp_src);        *pp_src = NULL;    }    return dest;}/** * 清空链表 * @param plist 链表指针 * @return      1:成功 0:失败 */int linked_list_clear(linked_list *plist){    int ret = ((plist != NULL) && (plist->length != 0));    if(ret)    {        /*         * 这种清空的循环不妥,当外部恶意修改了plist->length,那么将会发生内存泄漏        int i;        for(i = 0;i < plist->length;i++)        {            ll_node *del = plist->head.next;            plist->head.next = del->next;            free(del);        }        */        ll_node *head = &(plist->head);        while(head->next != NULL)        {            ll_node *del = head->next;            head->next = del->next;            free(del);        }        plist->length = 0;    }    return ret;}/** * 销毁链表 * @param plist 链表指针 * @return      1:成功 0:失败 */int linked_list_destroy(linked_list *plist){    int ret = (plist != NULL);    if(ret)    {        linked_list_clear(plist);        free(plist);    }    return ret;}


原创粉丝点击