C Datastructure 2 ---- link list(1)

来源:互联网 发布:怎样创造软件 编辑:程序博客网 时间:2024/05/16 05:37

上一篇我们学习了线性表,但是线性表有一个缺点,就是表满了之后就不能再插入了,所以就有了今天的链表(link list)。
链表又分好几种:

  • 单向链表(single link list)
  • 循环链表(circular link list)
  • 双向链表(double link list)
  • 静态链表(static link list)

今天我们先了解下最简单的单项链表。 单项链表github源码链接
定义数据结构

typedef int ElementType;typedef struct stNode {    ElementType data;    struct stNode *next;}stNode;typedef struct stNode* pstLinkList;

定义接口

BOOL InitList(pstLinkList* pstll, int n);BOOL IsListEmpty(pstLinkList pstll);BOOL GetptrList(pstLinkList pstll, int index, pstLinkList* pll);BOOL GetElem(pstLinkList pstll, int index, ElementType * elem);BOOL GetIndex(pstLinkList pstll, ElementType elem, int* index);void GetLength(pstLinkList pstll, int* len);BOOL InsertElem(pstLinkList pstll, int index, ElementType elem);BOOL PushElem(pstLinkList pstll, ElementType elem);BOOL DeletElem(pstLinkList pstll, int index);BOOL PopElem(pstLinkList pstll);void ClearList(pstLinkList pstll);void PrintList(pstLinkList pstll);

具体实现说几个比较重要的函数。

static BOOL CreatNode(pstLinkList* p) /* double ** */{    *p = (pstLinkList)malloc(sizeof(stNode));    if(!(*p))        return FALSE;    (*p)->next = NULL;    (*p)->data = 666;    return TRUE;}

这个是为了插入元素时创建一个节点用的。值得注意的是我们需要对节点的地址操作,而不是对节点的拷贝操作。也就是说这个函数的input只能是 pstLinkList* 类型,而不能是pstLinkList类型,否则只是对pstLinkList的一个对象的拷贝进行操作,并不能对我们想要的节点进行内存申请操作。

初始化一个表。

/** creat head point to first node*/BOOL InitList(pstLinkList* pstll, int n) /* double ** */{    int i;    pstLinkList pstnode,p;    CreatNode(pstll);//creat head pointer    p = *pstll;    for(i=0; i<n; i++)    {        CreatNode(&pstnode);        pstnode->data = i;        pstnode->next = p->next;        p->next = pstnode;    }    return TRUE;}

初始化一个表的时候和CreatNode函数都是需要我们提供节点的地址pstLinkList*, 而不是pstLinkList。

博主为了方便插入和删除元素,另外编写了一个查找某一个index下的节点地址的函数。

/** if index=0 ,return the head pointer* pll <----> index =0~len*/BOOL GetptrList(pstLinkList pstll, int index, pstLinkList* pll){    int count;    pstLinkList p;    p = pstll;//head pointer    count = 0;    while(p && index>=0)    {        if(index == count)        {            *pll = p;            return TRUE;        }        else        {            p = p->next;            count++;        }    }    *pll = NULL;    return FALSE;}

接下来就是最关键的插入删除表了。

/** insert node at index*/BOOL InsertElem(pstLinkList pstll, int index, ElementType elem){    pstLinkList p,pNode;    /*index>=1 && index <= len+1*/    if(GetptrList(pstll, index-1, &p))    {        CreatNode(&pNode);        pNode->data = elem;        pNode->next = p->next;        p->next = pNode;        return TRUE;    }    return FALSE;   }BOOL DeletElem(pstLinkList pstll, int index){    pstLinkList p,pDelNode;    if(GetptrList(pstll, index-1, &p))    {        pDelNode = p->next;        if(!pDelNode)//in case p is the end             return FALSE;        p->next = pDelNode->next;        free(pDelNode);        printf("free ok!\n");        return TRUE;    }    return FALSE;}

我们同样实现了PushElem、PopElem类似栈的操作,即在表尾插入或者删除一个元素。

BOOL PushElem(pstLinkList pstll, ElementType elem){    int len;    GetLength(pstll, &len);    return InsertElem(pstll,len+1,elem);}BOOL PopElem(pstLinkList pstll){    int len;    GetLength(pstll, &len);    return DeletElem(pstll,len);}

最后就是销毁一个表,这里尤其要注意,否则容易出现内存溢出(core dumped)错误。
也就是我们malloc了多少次,最终也要free掉多少次。
我的调试方法是设置一个全局变量malloc_cnt,在每一个内存分配的地方打印这个数据

printf("malloc count: %d\n", malloc_cnt++);

同样的,在没一个free的地方搞一个free_cnt,

printf("free count: %d\n", free_cnt++);

最后比较这两个数值就知道那个地方内存出错啦~
最后测试下我们的程序

int main(int argc, char const *argv[]){    pstLinkList pstll, pll;    ElementType elem;    int index,len;    if(!InitList(&pstll, 5))    {        printf("Init failed!\n");        ClearList(pstll);        return 0;    }    if(IsListEmpty(pstll))    {        printf("this link list is empty!\n");        ClearList(pstll);        return 0;    }    printf("link list elements are:\n");    printf("======\n");    PrintList(pstll);    printf("\n\n\n");    GetLength(pstll, &len);    printf("link list length: %d\n", len);    if(GetIndex(pstll, 3, &index))        printf("elem 3 at the index: %d\n",index);    else        printf("elem 3 is not existing in the link list\n");    if(GetElem(pstll, 4, &elem))        printf("elem at the index 4: %d\n", elem);    else        printf("index is not elligal!\n");    printf("\n\n\n");    printf("insert elem 90 at index 3: \n");    InsertElem(pstll, 3, 90);    printf("now, link list's elem are: \n");    PrintList(pstll);    printf("\n\n\n");    printf("push elem 88 at the end of the link list: \n");    PushElem(pstll, 88);    printf("now, link list's elem are: \n");    PrintList(pstll);    printf("\n\n\n");    printf("delet the elem at the index 1: \n");    DeletElem(pstll, 1);    printf("now, link list's elem are: \n");    PrintList(pstll);    printf("\n\n\n");    printf("pop elem at the the end of the link list\n");    PopElem(pstll);    printf("now, link list's elem are: \n");    PrintList(pstll);    printf("\n\n\n");    printf("clear the list...\n");    ClearList(pstll);    printf("link list datastructure exercise is the end...\n");    printf("see u ^_^ !\n");    printf("\n\n\n");    return 0;}
0 0
原创粉丝点击