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
- C Datastructure 2 ---- link list(1)
- C Datastructure 3 ---- link list(2)
- C Datastructure 4 ---- link list(3)
- C Datastructure 1 ---- linear list
- The Link List with C
- C Datastructure 5 ---- stack
- DataStructure-用数组实现List
- DataStructure-用指针实现List
- Datastructure c++ note 2
- DataStructure-2-线性表
- Datastructure c++ note 1
- DataStructure-1-基础
- 【DataStructure】Descriptioin and usage of List
- 【DataStructure】Another usage of List: Polynomial
- Link List
- link list
- DataStructure----LinerList,线性表C实现
- DataStructure---LinkList 链表C语言实现代码
- JavaSE-Http断点/多线程下载文件
- 多线程读脏数据问题
- webview在android端基本用法(三)
- Struts2 输入域名跳转到首页(不改变浏览器地址栏地址)
- 【caffe install】recipe for target 'xxx' failed
- C Datastructure 2 ---- link list(1)
- CentOS 7下 docker pull加速 亲测可用
- 缺少动态连接库.so--cannot open shared object file: No such file or directory
- afx.h与window.h
- yum 安装启动httpd
- ubuntn 16.04.2下caffee的安装教程
- 被坑水题——Codeforces Round #408 (Div. 2)
- 用octopress搭建博客时遇到的一些问题
- 设计模式_装饰模式概述和使用