穷究链表(五)
首先根据第四篇中的原则,将想要实现的链表操作确定下来
1.添加
void addnode(listnode* header, listnode* newnode, int pos);
2.删除
void deletenode(listnode* header, int pos)
3.遍历
void printlist(listnode *header)
4.倒序
void reverselist(listnode *header)
5.两个链表合并
void combinelist(listnode *header, listnode *list2)
6. 查找特定节点
listnode* findnode(listnode *header, int pos)
在这些都定下来之后,那我们可以去实现代码了吧?
且慢,我们的目的并不是要提供一个可以运行的程序,而是从中能够学到些什么,编写出优美的代码。
那为什么不看看其他人的设计呢?如果相同,赞一下自己,如果不同,思考一下到底是谁的好(不要迷信权威,尽信书不如无书),如果别人的好,那他是怎么思考的,然后将自己的设计修改过来。
这里,我们就需要知道现在有哪些好的已经实现好的库代码。
如果我们要看strcpy, strcmp, strstr等,C的库函数中就有了,在linux的内核代码中也实现了一份,都可以参考。但是对于链表等数据结构,C的库函数中是不提供这些的。而linux中的链表实现太过晦涩,不是现在需要了解的内容(当然,后面会去进行研究的)。那我们去哪里找到参考呢?
我挑选的是数据结构的书籍。其中C语言描述的实现代码。后面对于C++的,也会有对应的书籍进行参考。
国内为《数据结构(C语言版)》 作者为 严蔚敏,为蓝色封面,其豆瓣链接为:
http://www.douban.com/subject/1101779/
国外的为《Data Structures and Algorithm Analysis in C》,豆瓣的链接为
http://www.douban.com/subject/1237002/
这本书在CSDN上有电子版下载,大家如果需要,可以去那里下载到。
具体如何选择顺序,就看各人的喜好了,有些人喜欢先看,有些人喜欢先实现,因为看就是看到代码的层面了,你看的话,代码也全部看到了,在后面实现的时候,你也会受到其代码的影响,所以,如果你先实现的话,也是很好的。
当然,很多C库都自己实现了链表,如果你能够阅读这些链表的实现的话,那也是很好的,但是其中注意一些问题。
比如typedef会定义很多,这个应该是从微软开始的吧,并不是不好,但是最好就是找到其最终的那个定义类型是长什么样的。
同时,库代码中为了很好的兼容性,加上了很多ifdef...endif宏。在阅读代码的过程中,会感觉很差,不过也没有办法避免。但是在自己实现代码时,不是工程级代码,不需要像那样进行实现,反而扰乱了思路。
我现在能够想到的大概就是GNU的C库了。不过glibc大概也是C标准库,不包含链表。如果有谁知道一些好的C的实现,请告诉我,多谢了。
还有就是,在实现代码的时候,测试代码写好对于无论实现代码还是测试都是很有帮助的。可以在定义好这些接口函数之后,便开始着手编写代码。不过,测试代码如何写?则是另一个课题。
事实上,尽管有这个念头,我也还是先实现再编写“测试”代码的。知易行难。尤其是没有测试框架支持和流程约束的时候。
不过,经过查看两本书的内容,发现其实现的都是有头节点的链表,和我这里要实现的并不相同,所以能够参考的就少了。实际上,一般都会牺牲一点点的空间来换取开发的方便的。像我这样自找苦吃的,也只有实验数据结构的时候了吧~~~
另外,在实现链表操作的时候,有插入和删除动作时,有时会修改到链表本身,而C为值传递,此时就需要小心了。
最有名的例子应该就是这个了
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
需要修改值,就需要使用指针来做为参数;我如果需要修改指针的值,就需要使用指针的指针来做为参数。
所以,最后的实现为
typedef listnode* linkedlist;
void addNode(linkedlist *llist, listnode *newnode, int pos)
void deleteNode(linkedlist *llist, int pos)
void printlist(linkedlist llist)
linkedlist reverselist(linkedlist* llist)
linkedlist mergelist(linkedlist* llist, linkedlist llist2)
listnode* findNode(linkedlist llist, int pos)
在这样定义完原型之后,我们就可以来一个个实现了。