C语言实现单链表-03版
在C语言实现单链表-02版中我们只是简单的更新一下链表的组织方式;
它没有更多的更新功能,因此我们这个版本将要完成如下功能:
Problem
1,搜索相关节点;
2,前插节点;
3,后追加节点;
4,一个专门遍历数据的功能;
Solution
我们的数据结构体定义如下,和上一个版本稍微有所不同;
例如,我们把人这个结构体添加一个name域,前几个版本没有名字的节点;
我们叫起来很尴尬,都是第几个第几个节点,好啦!现在有名字啦!
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef struct person_ {
int hight;
int weight;
char name[];
}Person; typedef struct node_ {
Person *data;
struct node_ * next;
}Node; typedef struct link_list_ {
Node * head;
Node * tail;
int size;
}Link_List;
和第二版本一样,我们需要创建节点的函数;
还需要创建链表的函数;
还有一个插入函数;
Node * create_node(void *data)
{
Node * tmp = (Node*)malloc(sizeof(Node));
if(tmp) {
tmp->data = data;
tmp->next = NULL;
}
return tmp;
} Link_List * init_list(void)
{
Link_List * lst = (Link_List*)malloc(sizeof(Link_List));
lst->head = lst->tail = NULL;
lst->size = ;
return lst;
} void insert(Link_List * lst,void *data)
{
Node * new_node = create_node(data);
if(lst->size == ) {
lst->tail = new_node;
}
new_node->next = lst->head;
lst->head = new_node;
lst->size++;
}
好啦!这些函数都没有注释,第一个原因可以认为我很懒;
第二个原因是可以认为这太简单啦,以至于我们不希望看到多余的注释;
好啦!我们第三版的第一个函数,遍历输出节点的函数:
void travel(Link_List * root)
{
if(root) {
Node * we = root->head;
while(we != NULL) {
printf("Name:%s--Hight:%d--Weight:%d\n",we->data->name,we->data->hight,we->data->weight);
we = we->next;
}
}
return ;
}
我们暂时不测试它先,因为要是测试它,我们留着待会一起测试;
继续,写我们的查找函数,它能够按照给定的名字查找我们的节点哦;
Node * search_by_name(Link_List * lst, char * name)
{
Node * target = lst->head;
while (target != NULL ){
if(!strcmp(target->data->name,name)) {
puts("Found it");
return target;
}
target = target->next;
}
puts("Cannot found it");
return NULL;
}
若是找到啦!会提示我们的,并且返回找的的节点;
当然要是你有同名的节点,它只会把第一个找到得送给你哦;
(这里考虑一下,要是,第一个找到得不是你期望的哪个,你该怎么实现继续往下查找呢)
要是找不到目标节点也会提示我们的,并且返回空指针;
如果成功找到了目标节点,你肯定想看看它长啥样;
所以我们需要一个函数描述它:
void node_detail(Node * node)
{
if(node) {
printf("The detail of target node >>Name: %s -- Hight: %d -- Weight: %d\n",node->data->name,node->data->hight,node->data->weight);
}
return ;
}
有时候我们找到了目标节点,并不是仅仅想看看它长什么样;
还想在它之后添加一个节点;
所以我们需要一个追加函数:
void append_after(Link_List * lst, Node * new, Node * old)
{
Node * target = lst->head;
while(target != NULL){
if(target == old){
new->next = old->next;
old->next = new;
puts("Append successful");
return ;
}
target = target->next;
}
return ;
}
好啦!哪有时候,我们并不想追加,我们想把一个新节点插入到某个节点之前;
该怎么做呢?
注意和前面的追加函数进行对比分析哈!因为他们非常相似;
void insert_before(Link_List *lst, Node * new, Node * old)
{
Node * target = lst->head;
while(target->next != NULL){
if(target->next == old){
new->next = target->next;
target->next = new;
puts("Insert successful");
return ;
}
target->next = target->next->next;
}
return ;
}
好啦!又到我们的测试代码部分啦!
int main(void)
{
Link_List * root = init_list(); Person a = { , , "Frank" };
Person b = { , , "Jack" };
Person c = { , , "Landpack" }; insert(root,&a);
insert(root,&b);
insert(root,&c); //test travel function
travel(root); return ;
}
测试结果:

好啦!继续测试搜索查找节点的功能:
int main(void)
{
Link_List * root = init_list(); Person a = { , , "Frank" };
Person b = { , , "Jack" };
Person c = { , , "Landpack" }; insert(root,&a);
insert(root,&b);
insert(root,&c); //test travel function
travel(root); // test search node
Node * result = search_by_name(root,"Jack");
node_detail(result);
return ;
}
再看看查找结果,并且顺便看看我们的detail函数是否有效;

接下来就是追加函数和插入函数的测试啦;
好啦!首先是追加函数测试;
int main(void)
{
Link_List * root = init_list(); Person a = { , , "Frank" };
Person b = { , , "Jack" };
Person c = { , , "Landpack" }; insert(root,&a);
insert(root,&b);
insert(root,&c); //test travel function
travel(root); // test search node
Node * result = search_by_name(root,"Jack");
node_detail(result); // test append function
Person d = { ,,"Peter" };
Node * new_d = create_node(&d);
append_after(root,new_d,result);
travel(root); return ;
}
测试结果如下:

好啦!最后测试我们的插入函数:
int main(void)
{
Link_List * root = init_list(); Person a = { , , "Frank" };
Person b = { , , "Jack" };
Person c = { , , "Landpack" }; insert(root,&a);
insert(root,&b);
insert(root,&c); //test travel function
travel(root); // test search node
Node * result = search_by_name(root,"Jack");
node_detail(result); // test append function
Person d = { ,,"Peter" };
Node * new_d = create_node(&d);
append_after(root,new_d,result);
travel(root); // test insert function
Person e = { ,,"Sap" };
Node * new_e = create_node(&e);
insert_before(root,new_e,result);
travel(root); return ;
}
测试结果如下:

好啦!我们本次版本更新的所有的任务完成啦!
要是项目经理满意的话会请我们喝啤酒啦!
所有代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef struct person_ {
int hight;
int weight;
char name[];
}Person; typedef struct node_ {
Person *data;
struct node_ * next;
}Node; typedef struct link_list_ {
Node * head;
Node * tail;
int size;
}Link_List; Node * create_node(void *data)
{
Node * tmp = (Node*)malloc(sizeof(Node));
if(tmp) {
tmp->data = data;
tmp->next = NULL;
}
return tmp;
} Link_List * init_list(void)
{
Link_List * lst = (Link_List*)malloc(sizeof(Link_List));
lst->head = lst->tail = NULL;
lst->size = ;
return lst;
} void insert(Link_List * lst,void *data)
{
Node * new_node = create_node(data);
if(lst->size == ) {
lst->tail = new_node;
}
new_node->next = lst->head;
lst->head = new_node;
lst->size++;
}
void travel(Link_List * root)
{
if(root) {
Node * we = root->head;
while(we != NULL) {
printf("Name:%s--Hight:%d--Weight:%d\n",we->data->name,we->data->hight,we->data->weight);
we = we->next;
}
}
return ;
} Node * search_by_name(Link_List * lst, char * name)
{
Node * target = lst->head;
while (target != NULL ){
if(!strcmp(target->data->name,name)) {
puts("Found it");
return target;
}
target = target->next;
}
puts("Cannot found it");
return NULL;
} void node_detail(Node * node)
{
if(node) {
printf("The detail of target node >>Name: %s -- Hight: %d -- Weight: %d\n",node->data->name,node->data->hight,node->data->weight);
}
return ;
} void append_after(Link_List * lst, Node * new,Node * old)
{
Node * target = lst->head;
while(target != NULL){
if(target == old){
new->next = old->next;
old->next = new;
puts("Append successful");
return ;
}
target = target->next;
}
return ;
}
void insert_before(Link_List *lst, Node * new, Node * old)
{
Node * target = lst->head;
while(target->next != NULL){
if(target->next == old){
new->next = target->next;
target->next = new;
puts("Insert successful");
return ;
}
target->next = target->next->next;
}
return ;
} int main(void)
{
Link_List * root = init_list(); Person a = { , , "Frank" };
Person b = { , , "Jack" };
Person c = { , , "Landpack" }; insert(root,&a);
insert(root,&b);
insert(root,&c); //test travel function
travel(root); // test search node
Node * result = search_by_name(root,"Jack");
node_detail(result); // test append function
Person d = { ,,"Peter" };
Node * new_d = create_node(&d);
append_after(root,new_d,result);
travel(root); // test insert function
Person e = { ,,"Sap" };
Node * new_e = create_node(&e);
insert_before(root,new_e,result);
travel(root); return ;
}
Discussion
我们的链表似乎挺棒啦!但是烦人的项目经理是不会满足的;
他说下次版本更新,最好添加一个删除节点的功能;
(因为他可能想解聘一些员工啦!希望不会是我哦)
还有。。。。
他说反正有很大任务的。。。。
哈哈下次见;
C语言实现单链表-03版的更多相关文章
- C语言实现单链表-02版
我们在C语言实现单链表-01版中实现的链表非常简单: 但是它对于理解单链表是非常有帮助的,至少我就是这样认为的: 简单的不能再简单的东西没那么实用,所以我们接下来要大规模的修改啦: Problem 1 ...
- C语言实现单链表-01版
单链表的应用非常广,它可以实现栈,队列等: Problem 我对学习任何东西都希望能找到尽可能简单的例子,而不是看起来好高大上的: 对链表这样简答的数据结构,有些书也是写得太过“完美”啦: 初学者很难 ...
- C语言实现单链表-04版
前面的版本似乎没能让项目经理满意,他还希望这个链表有更多的功能: 我们接下来要解决几个比较简单的功能: Problem 1,更加友好的显示数据: 2,能够通过名字删除节点: Solution 首先我们 ...
- C语言实现单链表,并完成链表常用API函数
C语言实现单链表,并完成链表常用API函数: 1.链表增.删.改.查. 2.打印链表.反转打印.打印环形链表. 3.链表排序.链表冒泡排序.链表快速排序. 4.求链表节点个数(普通方法.递归方法). ...
- C语言实现单链表节点的删除(带头结点)
我在之前一篇博客<C语言实现单链表节点的删除(不带头结点)>中具体实现了怎样在一个不带头结点的单链表的删除一个节点,在这一篇博客中我改成了带头结点的单链表.代码演示样例上传至 https: ...
- C/C++语言实现单链表(带头结点)
彻底理解链表中为何使用二级指针或者一级指针的引用 数据结构之链表-链表实现及常用操作(C++篇) C语言实现单链表,主要功能为空链表创建,链表初始化(头插法),链表元素读取,按位置插入,(有序链表)按 ...
- 「C语言」单链表/双向链表的建立/遍历/插入/删除
最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合, ...
- 一起talk C栗子吧(第十二回:C语言实例--单链表一)
各位看官们,大家好.从今天開始,我们讲大型章回体科技小说 :C栗子.也就是C语言实例.闲话休提, 言归正转. 让我们一起talk C栗子吧! 看官们,上一回中咱们没有说详细的样例,并且是说了样例中的文 ...
- C语言实现单链表(不带头结点)节点的插入
对单链表进行增删改查是最主要的操作.我在上一篇博客<C语言实现链表节点的删除>实现了删除单链表中的某个节点. 这里我们要来实如今某个位置插入节点.演示样例代码上传至https://gith ...
随机推荐
- hdu 1348 Wall (凸包)
Wall Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- jQuery Mobile 过渡效果
jQuery Mobile 包含了允许您选择页面打开方式的 CSS 效果. jQuery Mobile 过渡效果 jQuery Mobile 拥有一系列关于如何从一页过渡到下一页的效果. 注释:如需实 ...
- HTTP 初步知识总结
1.HTPP报文 HTTP协议以报文的格式传递数据,报文有三部分组成:起始行(对报文进行描述),首部块(包含属性),主体(包含数据,可选)所有的HTTP报文都可以分为两类:请求报文(Requset M ...
- MVC5+EF6 简易版CMS(非接口) 第二章:建数据模型
目录 简易版CMS后台管理系统开发流程 MVC5+EF6 简易版CMS(非接口) 第一章:新建项目 MVC5+EF6 简易版CMS(非接口) 第二章:建数据模型 MVC5+EF6 简易版CMS(非接口 ...
- unreal3的viewport和client
名字里带viewport/client的类不少,以及相关的类: FViewportFrame.FViewport FViewportClient/UScriptViewportClient/UGame ...
- [Linux]CentOS下安装和使用tmux
前天随意点开博客园,看到了一篇关于tmux的文章 Tmux - Linux从业者必备利器,特意还点进去看了.毕竟Linux对于做游戏服务端开发的我来说,太熟悉不过了.不过我就粗略地看了一眼,就关掉了. ...
- 在C代码中调用C++接口
一 在C源文件中调用C++封装的接口 例如: 要想在A.c文件中,调用生命在B.h,实现在B.cpp中的接口bool getMAC(char *mac_addr); 其实现方法 B.cpp 如下: / ...
- ubuntu下非本账户的.profile文件的修改
今天不小心在账户了修改了自己的.profile文件,导致重启之后账户无法进入,点登陆账户后黑屏后就重新回到账户登陆界面.一番折腾之后终于成功修改了原账户中的.profile文件,成功从新进入了原账户. ...
- js之事件
1.事件类型 鼠标事件 onclick事件 鼠标点击某个对象 ondblclick事件 鼠标双击某个对象 onmousedown事件 鼠标按下 onmouseup事件 鼠标松开 onmouseover ...
- archlinux 安装mysql-workbench
archlinux packages 官方沒有提供 mysql-workbench的直接安裝包 在aur裏面可以找到, 使用yaourt -S mysql-workbench 這裏有個依賴ctempl ...