链表

简介

  链表是一种常用的数据结构,它和数组的最大不同在于链表是随机分布可扩展的,而数组是连续分布不可扩展的。因为链表强大的可扩展性,几乎所有的语言都有内置的标准链表库,比如java实现List<T>接口的类,C++STL中的list<typename T>等。

链表图示

链表说明

  如图,链表中的每一项都是由两部分组成。第一部分是数据段,第二部分是指向下一项的指针。最后一项的指针为空表示什么都不指向。另外由于指针需要指向链表中的下一项,因此指针的类型是该结构体类型。

插入图示

插入说明

  如图所示,链表的存储方式决定了链表的插入及其快捷与简单。只需要删除将插入位置的前一项的指针指向插入项,而插入项的指针指向后一项即可。一般链表的实现是把数据插入到末尾,但将数据插入到其他的位置也是非常快捷的。

删除图示

删除说明

  如图所示,同插入一样,链表的存储方式也使得删除操作变得简单。只需要将指向待删除位置的指针指向删除位置的后一项,而删除项的指针置为空即可。

修改与查找

  链表的修改与查找并不需要修改指针,所以相比于数组,并没有任何性能上的提升。相反链表丢失了数组的随机访问能力,在某些情况下反而不如数组。

附注

  在插入与删除操作中由于不需要对后续元素的操作,所以时间复杂度位θ(1),远远优于数组。 而在修改与查找操作中需要对整个链表遍历来找出目标元素,所以时间复杂度为θ(N),和数组并无区别。

简单链表库

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

struct Node
{
    int num;
};

typedef struct List
{
    struct Node node;
    struct List *next; 
}type;

typedef type* List;

/*
 *对目标列表进行初始化
 *@plist : 目标列表
 */
void InitializeList(List * plist)
{
    *plist = NULL;
}
/*
 *对两个参数进行比较。
 *@node1: 第一个参数
 *@node2: 第二个参数
 *@return: node1 > node2 -> 1, node1 < node2 -> -1, equal -> 0
 */
static int CompareNode(struct Node node1, struct Node node2)
{
    if(node1.num > node2.num)
        return 1;
    if(node1.num < node2.num)
        return -1;
    return 0;
}
/*
 *将数据添加到链表的结尾
 *@plist: 目标链表
 *@vnode: 待插入项
 *@return: 是否成功添加
 */
bool AddList(List *plist, struct Node vnode)
{
    List mlist = malloc(sizeof(type)); // C语言会进行自动转换,不需要强制转换。C++需要强制类型转换
    if(mlist == NULL)
        return false;
    mlist -> node = vnode;
    mlist -> next = NULL;

    if(*plist == NULL)  // 目标链表为空
    {
        *plist = mlist;
        return true;
    }
    // 目标链表不为空
    List tlist = *plist;
    while(tlist -> next != NULL)
        tlist = tlist -> next;
    tlist -> next = mlist;
    return true;
}
/*
 *在链表中寻找目标项
 *@plist: 目标链表
 *@vnode: 目标项
 *@return: 指向目标项的指针, 不存在则返回NULL
 */
List FindInList(List *plist, struct Node vnode)
{
    if(*plist == NULL)
        return NULL;
    List tlist = *plist;
    while(tlist)
    {
        if(CompareNode(tlist -> node, vnode) == 0)
            return tlist;
        tlist = tlist -> next;
    }
    return NULL;
}
/*
 *将目标项插入到链表某个指定项的后面
 *@plist: 目标链表
 *@vnode: 指定项
 *@aimNode: 待插入项
 *@return: 是否成功插入
 */
bool InsertList(List *plist, struct Node vNode, struct Node aimNode)
{
    if(*plist == NULL)
        return false;

    List tlist = FindInList(plist, vNode);
    if(tlist == NULL)
        return false;

    List aimlist = malloc(sizeof(type));
    if(aimlist == NULL)
        return false;
    aimlist -> node = aimNode;
    aimlist -> next = tlist -> next;
    tlist -> next = aimlist;
    return true;
}
/*
 *在指定链表中删除指定项
 *@plist: 目标链表
 *@vnode: 指定待删除项
 *@return: 是否成功删除
 */
 bool DeleteInList(List *plist, struct Node vnode)
 {
    if(*plist == NULL)
        return false;

    List tlist = FindInList(plist, vnode);
    if(tlist == NULL)
        return false;
    
    List mlist = *plist;
    while(mlist -> next != tlist)
        mlist = mlist -> next;
    mlist -> next = tlist -> next;
    free(tlist);
    return true;
 }

/*
 *统计在指定链表中元素的个数
 *@plist: 目标链表
 *@return: 元素的个数
 */
int CountList(List *plist)
{
    int count = 0;
    List tlist = *plist;
    while(tlist != NULL)
    {
        ++count;
        tlist = tlist -> next;
    }
    return count;
}
/*
 *替换链表中某个指定的元素
 *@plist: 目标链表
 *@vnode: 待替换元素
 *@tnode: 替换元素
 *@return: 操作是否成功
 */
bool ReplaceInList(List *plist, struct Node vnode, struct Node tnode)
{
    if(*plist == NULL)
        return false;
    
    List tlist = FindInList(plist, vnode);
    if(tlist == NULL)
        return false;
    
    tlist -> node = tnode;
    return true;
}
/*
 *清空链表中所有的元素
 *@plist: 目标链表
 *@return: 是否清空整个链表
 @warning: 使用该函数后,整个链表都不可用。
 */
bool ClearAllList(List *plist)
{
    if(*plist == NULL)
        return true;
    
    List tlist;
    while(*plist)
    {
        tlist = (*plist) -> next;
        free(*plist);
        *plist = tlist;
    }
    return true;
}

 

posted on 2016-11-01 20:19  DevinSuMi  阅读(201)  评论(0编辑  收藏  举报