今天继续完善自己的链表,上次已经实现了链表的插入、遍历、销毁方法,对于链表的插入,我们上次是在头结点进行插入的,这次,我们来实现一个在任意结点进行插入的方法。

实现链表的另外一种插入方法----在任意位置进行插入:

在实现它之前,先实现获取任意位置的结点的函数,为便在实现任意插入时会使用到它,先在头文件中定义:

list.h:

#ifndef _LIST_H_
#define _LIST_H_#include <assert.h>typedef struct node
{int data;struct node* next;
} node_t;typedef void (*FUNC)(node_t*);node_t* list_insert_front(node_t* head, int data);void list_for_each(node_t* head, FUNC f);node_t* list_free(node_t* head);node_t* list_get_node(node_t* head, int index);//获取指定位置的结点#endif /* _LIST_H_ */

具体实现list.c:

#include "list.h"
#include <stdlib.h>node_t* list_insert_front(node_t* head, int data)
{node_t* n = (node_t*)malloc(sizeof(node_t));assert(n != NULL);n->data = data;n->next = NULL;if (head == NULL)head = n;else{n->next = head;head = n;}return head;
}void list_for_each(node_t* head, FUNC f)
{while (head){f(head);head = head->next;}
}node_t* list_free(node_t* head)
{node_t* tmp;while (head){tmp = head;head = head->next;free(tmp);}return head;
}node_t* list_get_node(node_t* head, int index)
{assert(index >= 0);int j = 0;while (head && j < index){head = head->next;j++;}if (j == index)//说明已经找到结点return head;return head;//说明最终head指向NULL,没有找到结点}

上面的也可简写:

node_t* list_get_node(node_t* head, int index)
{assert(index >= 0);int j = 0;while (head && j < index){head = head->next;j++;}return head;}

测试一下:

main.c:

#include "list.h"
#include <stdio.h>void print_node(node_t* n)
{printf("data=%d ", n->data);
}int main(void)
{node_t* head = NULL;head = list_insert_front(head, 30);head = list_insert_front(head, 20);head = list_insert_front(head, 10);list_for_each(head, print_node);putchar('\n');node_t* n = NULL;n = list_get_node(head, 1);if (n != NULL)printf("data = %d\n", n->data);elseprintf("not found\n");head = list_free(head);assert(head == NULL);return 0;
}

编译运行:

如果没有找到呢?

main.c:

int main(void)
{node_t* head = NULL;head = list_insert_front(head, 30);head = list_insert_front(head, 20);head = list_insert_front(head, 10);list_for_each(head, print_node);putchar('\n');node_t* n = NULL;n = list_get_node(head, 5);if (n != NULL)printf("data = %d\n", n->data);elseprintf("not found\n");head = list_free(head);assert(head == NULL);return 0;
}

编译运行:

好了,接着正式来定义任意插入的函数:

list.h:

#ifndef _LIST_H_
#define _LIST_H_#include <assert.h>typedef struct node
{int data;struct node* next;
} node_t;typedef void (*FUNC)(node_t*);node_t* list_insert_front(node_t* head, int data);void list_for_each(node_t* head, FUNC f);node_t* list_free(node_t* head);node_t* list_get_node(node_t* head, int index);node_t* list_insert_at(node_t* head, int data, int index);#endif /* _LIST_H_ */

list.c:

#include "list.h"
#include <stdlib.h>node_t* list_insert_front(node_t* head, int data)
{node_t* n = (node_t*)malloc(sizeof(node_t));assert(n != NULL);n->data = data;n->next = NULL;if (head == NULL)head = n;else{n->next = head;head = n;}return head;
}void list_for_each(node_t* head, FUNC f)
{while (head){f(head);head = head->next;}
}node_t* list_free(node_t* head)
{node_t* tmp;while (head){tmp = head;head = head->next;free(tmp);}return head;
}node_t* list_get_node(node_t* head, int index)
{assert(index >= 0);int j = 0;while (head && j < index){head = head->next;j++;}return head;}node_t* list_insert_at(node_t* head, int data, int index)
{assert(index >= 0);if (index == 0)//等于就是头插入结点,直接调用现成的方法return list_insert_front(head, data);node_t* p;p = list_get_node(head, index - 1);if (p == NULL){fprintf(stderr, "error insert pos\n");exit(EXIT_FAILURE);}
  //新建一个节点node_t* n = (node_t*)malloc(sizeof(node_t));assert(n != NULL);n->data = data;n->next = NULL;
  //将节点进行链接n->next = p->next;p->next = n;return head;
}

说明:

①fprintf表示向什么地方输出,如fprintf(stdio,"hello!");等价于printf("hello!");

②exit()表示程序退出,参数EXIT_FAILURE代表错误退出,它还有另外一个宏定义EXIT_SUCCESS,代表成功退出

程序测试:

main.c:

#include "list.h"
#include <stdio.h>void print_node(node_t* n)
{printf("data=%d ", n->data);
}int main(void)
{node_t* head = NULL;head = list_insert_front(head, 30);head = list_insert_front(head, 20);head = list_insert_front(head, 10);list_for_each(head, print_node);putchar('\n');node_t* n = NULL;n = list_get_node(head, 1);if (n != NULL)printf("data = %d\n", n->data);elseprintf("not found\n");head = list_insert_at(head, 15, 1);list_for_each(head, print_node);putchar('\n');head = list_free(head);assert(head == NULL);return 0;
}

编译:

其中的fprintf需要头文件:

所以在list.c中加入此头文件:

再次编译,运行:

如果插入失败会怎样呢?

#include "list.h"
#include <stdio.h>void print_node(node_t* n)
{printf("data=%d ", n->data);
}int main(void)
{node_t* head = NULL;head = list_insert_front(head, 30);head = list_insert_front(head, 20);head = list_insert_front(head, 10);list_for_each(head, print_node);putchar('\n');node_t* n = NULL;n = list_get_node(head, 1);if (n != NULL)printf("data = %d\n", n->data);elseprintf("not found\n");head = list_insert_at(head, 15, 5);//这个位置没有元素,应该会插入失败list_for_each(head, print_node);putchar('\n');head = list_free(head);assert(head == NULL);return 0;
}

编译运行:

实现链表的删除方法:

先定义删除方法:

list.h:

#ifndef _LIST_H_
#define _LIST_H_#include <assert.h>typedef struct node
{int data;struct node* next;
} node_t;typedef void (*FUNC)(node_t*);node_t* list_insert_front(node_t* head, int data);void list_for_each(node_t* head, FUNC f);node_t* list_free(node_t* head);node_t* list_get_node(node_t* head, int index);node_t* list_insert_at(node_t* head, int data, int index);node_t* list_remove_at(node_t* head, int index);#endif /* _LIST_H_ */

具体实现,在实现前,先用一个简单的图来解释下:

具体实现如下list.c:

node_t* list_remove_at(node_t* head, int index)
{assert(index >= 0);node_t* n;if (index == 0)//这是移除首结点{n = head;head = head->next;free(n);}else{node_t* p = list_get_node(head, index - 1);if (p == NULL || p->next == NULL){fprintf(stderr, "error remove pos\n");exit(EXIT_FAILURE);}n = p->next;p->next = n->next;free(n);}return head;
}

测试一下main.c:

#include "list.h"
#include <stdio.h>void print_node(node_t* n)
{printf("data=%d ", n->data);
}int main(void)
{node_t* head = NULL;head = list_insert_front(head, 30);head = list_insert_front(head, 20);head = list_insert_front(head, 10);list_for_each(head, print_node);putchar('\n');node_t* n = NULL;n = list_get_node(head, 1);if (n != NULL)printf("data = %d\n", n->data);elseprintf("not found\n");head = list_insert_at(head, 15, 1);list_for_each(head, print_node);putchar('\n');head = list_remove_at(head, 1);list_for_each(head, print_node);putchar('\n');head = list_free(head);assert(head == NULL);return 0;
}

编译运行:

如果移除的元素不存在呢?

#include "list.h"
#include <stdio.h>void print_node(node_t* n)
{printf("data=%d ", n->data);
}int main(void)
{node_t* head = NULL;head = list_insert_front(head, 30);head = list_insert_front(head, 20);head = list_insert_front(head, 10);list_for_each(head, print_node);putchar('\n');node_t* n = NULL;n = list_get_node(head, 1);if (n != NULL)printf("data = %d\n", n->data);elseprintf("not found\n");head = list_insert_at(head, 15, 1);list_for_each(head, print_node);putchar('\n');head = list_remove_at(head, 5);//这个元素不存在,移除时会出错list_for_each(head, print_node);putchar('\n');head = list_free(head);assert(head == NULL);return 0;
}

运行:

实现链表的查找方法:

list.h:

#ifndef _LIST_H_
#define _LIST_H_#include <assert.h>typedef struct node
{int data;struct node* next;
} node_t;typedef void (*FUNC)(node_t*);node_t* list_insert_front(node_t* head, int data);void list_for_each(node_t* head, FUNC f);node_t* list_free(node_t* head);node_t* list_get_node(node_t* head, int index);node_t* list_insert_at(node_t* head, int data, int index);node_t* list_remove_at(node_t* head, int index);node_t* list_find(node_t* head, int data, int* ret);//ret代表找到的链表的索引位置,返回值代表找到的链表结点#endif /* _LIST_H_ */

list.c:

#include "list.h"
#include <stdlib.h>
#include <stdio.h>node_t* list_insert_front(node_t* head, int data)
{node_t* n = (node_t*)malloc(sizeof(node_t));assert(n != NULL);n->data = data;n->next = NULL;if (head == NULL)head = n;else{n->next = head;head = n;}return head;
}void list_for_each(node_t* head, FUNC f)
{while (head){f(head);head = head->next;}
}node_t* list_free(node_t* head)
{node_t* tmp;while (head){tmp = head;head = head->next;free(tmp);}return head;
}node_t* list_get_node(node_t* head, int index)
{assert(index >= 0);int j = 0;while (head && j < index){head = head->next;j++;}return head;}node_t* list_insert_at(node_t* head, int data, int index)
{assert(index >= 0);if (index == 0)return list_insert_front(head, data);node_t* p;p = list_get_node(head, index - 1);if (p == NULL){fprintf(stderr, "error insert pos\n");exit(EXIT_FAILURE);}node_t* n = (node_t*)malloc(sizeof(node_t));assert(n != NULL);n->data = data;n->next = NULL;n->next = p->next;p->next = n;return head;
}node_t* list_remove_at(node_t* head, int index)
{assert(index >= 0);node_t* n;if (index == 0){n = head;head = head->next;free(n);}else{node_t* p = list_get_node(head, index - 1);if (p == NULL || p->next == NULL){fprintf(stderr, "error remove pos\n");exit(EXIT_FAILURE);}n = p->next;p->next = n->next;free(n);}return head;
}node_t* list_find(node_t* head, int data, int* ret)
{*ret = -1;int i = 0;while (head){if (head->data == data){*ret = i;break;}head = head->next;i++;}return head;
}

测试main.c:

#include "list.h"
#include <stdio.h>void print_node(node_t* n)
{printf("data=%d ", n->data);
}int main(void)
{node_t* head = NULL;head = list_insert_front(head, 30);head = list_insert_front(head, 20);head = list_insert_front(head, 10);list_for_each(head, print_node);putchar('\n');node_t* n = NULL;n = list_get_node(head, 1);if (n != NULL)printf("data = %d\n", n->data);elseprintf("not found\n");head = list_insert_at(head, 15, 1);list_for_each(head, print_node);putchar('\n');head = list_remove_at(head, 1);list_for_each(head, print_node);putchar('\n');int ret;n = list_find(head, 20, &ret);if (n != NULL)printf("data = %d index = %d\n", n->data, ret);elseprintf("not found\n");head = list_free(head);assert(head == NULL);return 0;
}

编译,运行:

好了,今天的学习到这,关于链表,下次会再次进行完善,下次见。

转载于:https://www.cnblogs.com/webor2006/p/3484812.html

指针应用-----链表二相关推荐

  1. c语言课程设计链表 文件,C语言课程设计第三节课:指针和链表使用     150809205...

    一.学习体会 C语言的难点就是指针,学习的时候感觉指针的难点在于与其相关的技术和方法很多,所以学习              的时候并不能像前边一样一个知识点一道题就明白了. 二.以下是我对指针原理的 ...

  2. 关于C语言的指针、链表的原理和各类操作

    今天课上我们老师为我们讲述了c语言的指针.链表的原理以及各类操作. 一.指针 1.指针 指针是一个存储计算机内存地址的变量.从指针指向的内存读取数据称作指针的取值.指针可以指向某些具体类型的变量地址, ...

  3. 【RTOS训练营】课程学习方法和C语言知识(指针、结构体、函数指针、链表)和学员问题

    一.课程学习方法 因为有些学员是刚进群,所以这里再把学习方法讲一下. 1. 预习 我们会在每一节晚课之后会通知要预习的章节,学员需要按如下操作观看相关视频. 1.1 打开百问网官网 ​1.2 点击首页 ...

  4. c语言用指针实现日期输出,C语言指针实现链表以及用gcc编译输出

    C语言指针实现链表以及用gcc编译输出 C语言指针实现链表以及用gcc编译输出 代码写的链表实现创建,插入,删除的操作,很基础的一些动作. 可以本地用NotePad写好代码,然后通过Filezilla ...

  5. 【刷题日记】3.复制带随机指针的链表

    目录 一.题目介绍 ​编辑 二.题目分析 三.代码实现 题目链接:138. 复制带随机指针的链表 - 力扣(LeetCode) 一.题目介绍 我们最一开始看到题目可能会没有思路,或者压根就不知道如何下 ...

  6. 关于指针和链表中的一些问题

    学习数据结构时对指针和链表很迷糊,也就自己总结 一下,如果有错误或者理解上的错误欢迎指正,谢谢 指针 指针是什么,指针就是指针类型,就和int 类型,float类型等一样,而对于指针个人当时学习的时候 ...

  7. python 带随机指针的链表深度复制_LeetCode:复制带随机指针的链表

    请实现 copyRandomList 函数,复制一个复杂链表.在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null. 思路: ...

  8. SDUT _2117 数据结构实验之链表二:逆序建立链表

    点击打开链接 数据结构实验之链表二:逆序建立链表 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem D ...

  9. C语言精要总结-指针系列(二)

    此文为指针系列第二篇: C语言精要总结-指针系列(一) C语言精要总结-指针系列(二) 指针运算 前面提到过指针的解引用运算,除此之外,指针还能进行部分算数运算.关系运算 指针能进行的有意义的算术运算 ...

最新文章

  1. python使用matplotlib可视化、查看matplotlib可视化中不同字体形式、不同字号、斜体可视化的效果对比
  2. 递归求嵌套数组中最大值
  3. 关于cocos2d的下载和安装
  4. 【算法】有关点分治的一些理解与看法
  5. 浅析Python中的序列化存储的方法
  6. Java12-day03【​​​​​​​(类名、抽象类名、接口名)作为形参和返回值、内部类、常用API(Math、System、toString()、Arrays)、冒泡】
  7. Ethercat解析(九)之过程数据
  8. Python IDE PyCharm2016.3.2(转)
  9. 独立游戏开发者---孤独前行的梦想家
  10. 卷积码 c语言编码,利用c语言实现卷积码编码器示例
  11. 14年macmini装双硬盘_苹果2014款Mac mini更换固态硬盘图文教程
  12. 太阳光轨迹软件_教你记录太阳的轨迹
  13. java案例_面向对象编程_Stool
  14. 渗透测试原理与基本进程
  15. 【VHDL语言学习笔记(二)】 4位向量加法器
  16. Linux: pam
  17. 莽撞小子终到迟暮中年 弗朗西斯择队目标转换(转)
  18. 数学建模之倚天剑与屠龙刀
  19. 云主机的优势有哪些?
  20. 电厂/矿井UWB室内定位解决方案

热门文章

  1. mybatis注解详解
  2. [CNT]关于自己的一个小小的slab内存分配器
  3. (三)Window的特色学习笔记
  4. java封装省市区三级json格式,2016中国省市区三级联动json格式.pdf
  5. Castor映射java对象
  6. CloudStack相关技术-主存储和二级存储
  7. leetcode算法题--子数组按位或操作
  8. JAVA黑白圆圈图形_CSS3 黑白交替旋转圆圈
  9. linux usb3.0改2.0,TX1入门教程硬件篇-切换USB2.0与USB3.0
  10. GoWorld – 用Golang写一个分布式可扩展、可热更的游戏服务器