c语言链表的用法
c链表库函数

c链表库函数全文共四篇示例,供读者参考第一篇示例:C语言是一种广泛应用于系统编程的高级语言,而链表(Linked List)是C语言中常用的数据结构之一。
在C语言中,链表并不像数组一样有现成的库函数可以直接调用,需要通过自定义函数来实现链表的操作。
为了方便使用链表,不少开发者封装了链表操作的库函数,提供了一些常用的链表操作接口,以供开发者使用。
本文将介绍一些常见的C链表库函数及其用法。
一、链表的概念及基本操作链表是一种线性表的存储结构,由若干节点(Node)组成,每个节点包含数据域和指针域。
数据域用于存放数据,指针域用于指向下一个节点。
链表的最后一个节点指针域为空(NULL),表示链表的末尾。
常见的链表操作包括创建链表、插入节点、删除节点、遍历链表、查找节点等。
下面我们来看看C语言中常用的链表库函数。
二、常见的C链表库函数1. 创建链表在C语言中,创建链表的函数通常包括初始化链表头节点和链表节点的操作。
```#include <stdio.h>#include <stdlib.h>//定义链表节点typedef struct node {int data;struct node* next;} Node;2. 插入节点插入节点是链表操作中的重要操作,可以在链表的任意位置插入新节点。
常见的插入方式包括头部插入和尾部插入。
```//头部插入节点void insertNodeAtHead(Node* head, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = head->next;head->next = newNode;}以上是常见的C链表库函数,这些函数可以帮助我们更方便地操作链表。
在实际开发中,可以根据需要自定义更多的链表操作函数,以满足具体的需求。
c语言超时重发机制的链表

c语言超时重发机制的链表C语言超时重发机制的链表引言:在网络通信中,超时重发机制是一种常见的应对网络延迟和丢包的技术手段。
本文将介绍如何使用C语言实现一个超时重发机制的链表,以及其原理和应用。
一、超时重发机制的链表超时重发机制的链表是一种数据结构,用于管理需要进行超时重发的数据包。
它的主要特点是可以按照发送顺序进行管理,并且能够自动检测超时并进行重发操作。
二、链表的基本结构链表是由一系列节点组成的数据结构,每个节点包含一个数据域和一个指针域。
在超时重发机制的链表中,每个节点代表一个数据包,并且需要额外包含超时时间和重发次数等信息。
三、链表的初始化在使用链表之前,需要进行初始化操作。
初始化操作主要包括创建链表头节点,并将头节点的指针域置空。
四、数据包的插入在发送数据包时,将数据包插入到链表的末尾。
这需要遍历链表,找到最后一个节点,并将其指针域指向新节点。
五、超时检测与重发超时检测是链表中的重要操作,用于判断是否有数据包超时。
当一个数据包超时时,需要将其重新发送,并更新超时时间和重发次数等信息。
六、数据包的删除当一个数据包发送成功后,需要从链表中删除。
删除操作需要遍历链表,找到对应的节点,并更新前后节点的指针域。
七、链表的销毁当所有数据包都发送完成或不再需要重发时,需要销毁链表。
销毁链表操作主要包括释放所有节点的内存空间,并将链表头节点的指针域置空。
八、超时重发机制的应用超时重发机制在网络通信中广泛应用于保证数据可靠性和提高传输效率。
例如,在TCP协议中,超时重发机制被用于保证数据包的可靠传输。
九、注意事项在实现超时重发机制的链表时,需要注意以下事项:1. 设置合理的超时时间,以适应不同的网络环境。
2. 避免重复发送已经成功发送的数据包,以节省网络带宽和资源。
3. 考虑异常情况,如网络中断或故障,需要对链表进行适当的处理。
结论:超时重发机制的链表是一种实现超时重发的重要数据结构。
它可以有效地应对网络延迟和丢包等问题,提高数据传输的可靠性和效率。
c语言中链表的定义

c语言中链表的定义C语言中链表的定义链表是一种常用的数据结构,它是由一系列节点组成的,每个节点包含一个数据元素和一个指向下一个节点的指针。
链表可以用来存储任意类型的数据,而且它的大小可以动态地增加或减少,非常灵活。
在C语言中,链表的定义通常包括两个部分:节点结构体和链表结构体。
节点结构体定义如下:```typedef struct node {int data; // 数据元素struct node *next; // 指向下一个节点的指针} Node;```这里定义了一个名为Node的结构体,它包含两个成员变量:data和next。
其中,data用来存储节点的数据元素,next用来指向下一个节点的指针。
注意,这里的next是一个指向Node类型的指针,这样才能实现链表的连接。
链表结构体定义如下:```typedef struct list {Node *head; // 指向链表头节点的指针Node *tail; // 指向链表尾节点的指针int size; // 链表的大小} List;```这里定义了一个名为List的结构体,它包含三个成员变量:head、tail和size。
其中,head和tail分别指向链表的头节点和尾节点,size表示链表的大小。
通过这两个结构体的定义,我们就可以创建一个链表了。
下面是一个简单的例子:```int main() {List list = {NULL, NULL, 0}; // 初始化链表Node *node1 = (Node*)malloc(sizeof(Node)); // 创建第一个节点node1->data = 1; // 设置节点的数据元素node1->next = NULL; // 设置节点的指针list.head = node1; // 将节点1设置为链表的头节点list.tail = node1; // 将节点1设置为链表的尾节点list.size++; // 链表大小加1// 创建更多的节点...return 0;}```在这个例子中,我们首先初始化了一个空链表,然后创建了第一个节点,并将它设置为链表的头节点和尾节点。
c语言二路归并链表

c语言二路归并链表二路归并链表是一种常见的链表操作,它主要用于将两个有序链表合并成一个新的有序链表。
在这篇文章中,我们将通过一个实际的例子来解释二路归并链表的思想和实现方法。
假设我们有两个有序链表,分别是链表A和链表B。
我们的目标是将这两个链表合并成一个新的有序链表。
要实现这个目标,我们可以使用递归或迭代的方法。
我们来看一下递归的方法。
递归的思想是将原问题拆分为多个子问题,然后通过解决子问题来解决原问题。
在二路归并链表中,我们可以将链表A的头节点与链表B的头节点进行比较,较小的节点作为新链表的头节点。
然后,我们将较小节点的下一个节点与另一个链表的头节点进行比较,重复这个过程,直到其中一个链表为空。
最后,我们将非空链表的剩余部分直接连接到新链表的末尾。
接下来,我们来看一下迭代的方法。
迭代的思想是通过循环来解决问题。
在二路归并链表中,我们可以使用两个指针分别指向链表A 和链表B的头节点。
然后,我们比较两个指针指向的节点的值,较小的节点作为新链表的节点,并将指针向后移动一位。
重复这个过程,直到其中一个链表为空。
最后,我们将非空链表的剩余部分直接连接到新链表的末尾。
无论是递归还是迭代的方法,二路归并链表的时间复杂度都是O(n+m),其中n和m分别是链表A和链表B的长度。
这是因为我们需要遍历链表A和链表B的所有节点,并将它们连接到新链表中。
通过以上的描述,我们可以看出,二路归并链表是一种非常实用的链表操作,它可以帮助我们将两个有序链表合并成一个新的有序链表。
无论是递归还是迭代的方法,都可以有效地实现这个目标。
希望通过这篇文章的介绍,读者能够更好地理解和掌握二路归并链表的思想和实现方法。
c++ 链表 表示方法

c++ 链表表示方法(实用版3篇)目录(篇1)1.C++链表概述2.链表表示方法3.链表的优势和劣势4.应用场景正文(篇1)C++链表是一种动态数据结构,可以动态地分配内存空间来存储数据。
链表由节点组成,每个节点包含数据和指向下一个节点的指针。
链表表示方法是一种将数据存储在节点中的方式,每个节点包含一个数据元素和一个指向下一个节点的指针。
链表的优势在于可以动态地分配内存空间,不需要预先分配固定大小的数组,因此可以适应不同大小的数据。
此外,链表还可以实现插入和删除操作,而不需要移动其他节点。
但是,链表也存在一些劣势,例如插入和删除操作的时间复杂度为O(n),其中n是链表的长度。
此外,链表的空间复杂度为O(1),而数组的空间复杂度为O(n)。
目录(篇2)1.C++链表概述2.链表表示方法3.链表的优势和劣势4.应用场景正文(篇2)C++链表是一种常见的数据结构,常用于实现动态内存分配和释放。
链表由节点组成,每个节点包含数据和指向下一个节点的指针。
链表可以动态地添加、删除和修改数据,并且不需要提前分配固定大小的内存空间。
链表的优势在于其动态性,可以在运行时根据需要分配内存空间,而不需要在编译时指定大小。
此外,链表还可以支持快速插入和删除操作,因为新的节点可以很容易地添加到链表的末尾。
但是,链表的劣势在于其需要使用额外的指针来连接节点,因此链表的内存开销比数组更大。
链表的应用场景非常广泛,包括字符串、链式存储结构、单向链表、双向链表、循环链表等。
在C++中,可以使用类来实现链表数据结构,并使用指针来管理内存。
目录(篇3)第一部分:链表的基本概念1.链表的定义和特点2.链表节点结构3.链表的插入和删除操作4.链表的遍历操作第二部分:链表的应用场景1.链表在数据结构中的应用2.链表在算法中的应用3.链表在游戏开发中的应用4.链表在物联网中的应用正文(篇3)C++ 链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
c语言数据结构链表基本操作

c语言数据结构链表基本操作C语言数据结构链表基本操作链表是一种常见的数据结构,用于存储和操作一系列的数据元素。
在C语言中,链表的实现通常使用指针来连接各个节点,每个节点包含数据和指向下一个节点的指针。
本文将介绍链表的基本操作,包括创建链表、插入节点、删除节点和遍历链表。
1. 创建链表创建链表的第一步是定义一个指向链表头节点的指针。
链表头节点是链表的起始位置,通常不存储数据,只用于指向第一个真正存储数据的节点。
可以使用malloc函数动态分配内存空间来创建链表节点,并将头指针指向该节点。
2. 插入节点在链表中插入节点分为两种情况:在链表头部插入和在链表中间或尾部插入。
在链表头部插入节点时,只需要创建一个新节点,并将新节点的指针指向原来的头节点,然后更新头指针指向新节点即可。
在链表中间或尾部插入节点时,需要先找到插入位置的前一个节点,然后创建新节点,并将新节点的指针指向原来的下一个节点,再将前一个节点的指针指向新节点。
3. 删除节点删除链表中的节点需要找到要删除节点的前一个节点,然后修改前一个节点的指针指向要删除节点的下一个节点,最后释放要删除节点的内存空间。
4. 遍历链表遍历链表是指依次访问链表中的每个节点,并对节点进行操作。
可以使用循环结构和指针来实现链表的遍历。
从链表头节点开始,通过指针指向下一个节点,直到指针为空或指向链表尾部。
链表的基本操作是在实际编程中经常使用的,它可以灵活地插入、删除和修改节点,适用于各种场景。
例如,可以使用链表来实现栈、队列等数据结构,也可以用于在内存中动态存储数据。
在使用链表时,需要注意以下几点:- 确保链表的头指针始终指向链表的起始位置,避免丢失链表的引用。
- 在插入和删除节点时,要注意更新链表的指针,以保持链表的正确性。
- 在释放链表内存空间时,要遍历链表并依次释放每个节点的内存空间,防止内存泄漏。
链表是一种重要的数据结构,灵活性和可扩展性使其在实际应用中具有广泛的用途。
c语言链表头插法
c语言链表头插法C语言是一门广泛应用于嵌入式系统和操作系统开发等领域的语言,而链表头插法是其中一种非常常用的数据结构处理方法。
本文主要围绕C语言链表头插法展开阐述,分为以下几个步骤:1. 了解链表的概念链表是一种常见的数据结构,它由一个个结点通过指针相连而组成。
每个结点包含两个部分:数据域和指针域。
数据域存储实际数据,指针域存储下一个结点的地址。
链表中第一个结点称为头结点,最后一个结点称为尾结点。
链表的特点是可以在任意位置方便地添加、删除和查找元素。
2. 理解头插法的含义头插法是一种在链表头部插入新结点的方法,相应的还有尾插法。
在操作时,先将新结点的指针域指向原头结点,再将头结点更新为新结点,从而实现在头部插入新元素。
尾插法则是在链表尾部添加新结点。
3. 理解链表头文件中结构体的定义链表通常需要定义一个结构体,用于存储每个结点的数据和指针域信息。
在C语言中链表结构体通常包含两个部分,分别是数据域和指针域。
例如下面的结构体定义:```struct Node{int data;struct Node *next;};```其中data存储结点数据,next存储指向下一个结点的指针。
next也可以用来表示链表的结束,当其指向NULL时,链表结束。
4. 实现链表头插法链表头插法的具体实现如下:```void list_add_head(struct Node **head, int data){// 创建新结点struct Node *new_node = (structNode*)malloc(sizeof(struct Node));new_node->data = data;// 更新头结点为新结点的指针new_node->next = *head;*head = new_node;}```该函数的参数是指向头结点指针的指针以及要插入的数据。
首先,在堆内存中创建一个新结点,然后将其指针域指向原头结点。
c语言链表递归逆序输出
c语言链表递归逆序输出链表是数据结构中常用的一种,在C语言中经常会用链表进行数据的存储和操作。
链表是由节点组成,每个节点都有一个指向下一个节点的指针。
在这篇文章中,我们将讨论如何使用递归来逆序输出一个链表。
步骤一:定义链表节点结构体在C语言中定义链表是一种非常常见的操作。
首先我们需要定义节点的结构体。
节点结构体通常包括一个数据域和一个指向下一个节点的指针域。
数据域用来存储节点的数据,指针域则用来表示指向下一个节点的指针。
结构体定义如下:```struct node {int data; // 数据域struct node *next; // 指针域};```步骤二:定义逆序输出函数接下来我们需要定义一个函数来逆序输出链表。
使用递归方法实现链表的逆序输出。
```void reversePrint(struct node *head){if(head == NULL) {return;}if(head->next != NULL){reversePrint(head->next);}printf("%d ", head->data);}```这个递归函数非常简单。
首先我们检查链表头指针是否为空。
如果为空,则返回(因为该链表中没有节点)。
然后我们检查是否有下一个节点。
如果有,则执行函数自身将下一个节点作为参数传递给它。
这样就可以将链表倒序遍历,最后输出节点的数据。
步骤三:测试函数我们可以使用以下代码来测试reversePrint函数:```int main() {struct node *head, *second, *third, *fourth;// 分配空间head = (struct node*)malloc(sizeof(struct node));second = (struct node*)malloc(sizeof(struct node));third = (struct node*)malloc(sizeof(struct node));fourth = (struct node*)malloc(sizeof(struct node));// 赋值head->data = 10;head->next = second;second->data = 20;second->next = third;third->data = 30;third->next = fourth;fourth->data = 40;fourth->next = NULL;// 逆序输出链表printf("链表逆序输出:\n");reversePrint(head);// 释放空间free(head);free(second);free(third);free(fourth);return 0;}```这里我们创建一个包含四个节点的链表,然后将该链表传递给我们刚刚定义的reversePrint函数。
c语言单链表尾插法
C语言单链表尾插法1. 简介单链表是一种常用的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
单链表尾插法是一种在链表尾部插入新节点的方法,通过将新节点插入到链表尾部,可以方便地实现链表的动态扩展和插入操作。
本文将详细介绍C语言中单链表尾插法的实现方法,包括链表结构的定义、节点的插入操作、遍历和释放链表等。
2. 链表结构定义在C语言中,我们可以通过结构体来定义链表的节点。
每个节点包含两个部分:数据域和指针域。
typedef struct Node {int data; // 数据域struct Node* next; // 指针域,指向下一个节点} Node;在上述代码中,我们定义了一个名为Node的结构体,其中data表示节点的数据,next表示指向下一个节点的指针。
通过typedef关键字,我们将struct Node重命名为Node,方便后续使用。
3. 节点的插入操作3.1 创建新节点在进行节点的插入操作之前,我们需要先创建一个新的节点。
可以通过动态内存分配函数malloc来分配内存,并使用free函数释放内存。
Node* createNode(int data) {Node* newNode = (Node*)malloc(sizeof(Node));if (newNode == NULL) {printf("内存分配失败\n");exit(1);}newNode->data = data;newNode->next = NULL;return newNode;}上述代码中,我们定义了一个名为createNode的函数,该函数接受一个整数参数data,用于初始化新节点的数据域。
首先使用malloc函数分配内存,并将返回的指针强制转换为Node*类型。
然后,我们检查内存分配是否成功,如果失败,则打印错误信息并调用exit函数退出程序。
接着,我们将新节点的数据域设置为传入的data值,指针域设置为NULL,最后返回新节点的指针。
c语言中的链表用法
c语言中的链表用法在C语言中,链表是一种常见的数据结构,用于存储一系列数据项,每个数据项称为节点,每个节点包含两个部分:数据和指向下一个节点的指针。
以下是一个简单的链表实现示例:```cinclude <>include <>// 定义链表节点结构体typedef struct Node {int data;struct Node next;} Node;// 创建新节点Node createNode(int data) {Node newNode = (Node)malloc(sizeof(Node));newNode->data = data;newNode->next = NULL;return newNode;}// 在链表末尾添加节点void appendNode(Node head, int data) { Node newNode = createNode(data); if (head == NULL) {head = newNode;return;}Node current = head;while (current->next != NULL) {current = current->next;}current->next = newNode;}// 打印链表void printList(Node head) {while (head != NULL) {printf("%d ", head->data);head = head->next;}printf("\n");}int main() {Node head = NULL; // 链表头指针初始化为NULLappendNode(&head, 1); // 添加节点1appendNode(&head, 2); // 添加节点2appendNode(&head, 3); // 添加节点3printList(head); // 打印链表:1 2 3return 0;}```在这个示例中,我们定义了一个链表节点结构体,其中包含一个整型数据成员和一个指向下一个节点的指针成员。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
c语言链表的用法c语言链表的用法链表是数据结构中比较基础也是比较重要的类型之一,那么有了数组,为什么我们还需要链表呢!或者说设计链表这种数据结构的初衷在哪里?下面店铺就为大家介绍下c语言链表的用法。
c语言枚举的用法如下:这是因为,在我们使用数组的时候,需要预先设定目标群体的个数,也即数组容量的大小,然而实时情况下我们目标的个数我们是不确定的,因此我们总是要把数组的容量设置的很大,这样以来就浪费了很多的空间。
另外,数组在进行插入操作和删除操作的时候,在插入或者删除制定元素之后,我们往往需要进行循环移位,这增加了我们的线性开销。
正是由于以上的两种主要原因,链表被设计出来用于一般表的操作。
为了避免上面描述数组的两种弊端,我们希望链表有一下的特点1 可以灵活的扩展自己的长度。
2 存储地址不连续,删除或者插入操作的时候不需要循环移位。
要实现以上两个特点,我们需既要保证每个节点的独立性,又要保存相邻两个节点的联系。
为此,链表一般被设计为下面的'形式。
Node--->Node---->Node链表是由一个一个的节点组成的,可以方便和自由的插入未知个Node,前一个节点中用指针保存着下一个节点的位置,这样以来便顺利的完成了我们对链表的两点期望,但是唯一的缺点是增加了额外的空间消耗。
————————————————————————————————————————————————————————————————————————————链表的定义:链表的定义一般使用结构体,在看《数据结构与算法分析》这本书的时候发现,书中频繁的使用typedef的关键字,结果真的很棒不仅保持的代码的整洁程度,也让我们在下面的编码过程中少见了很多烦人的指针(当然指针还是一直存在的)。
所以这里也借用了书中的定义方法。
struct Node;typedef struct Node* PtrNode;typedef PtrNode Position;typedef PtrNode List;struct Node{int Value;PtrNode Next;};下面接着书写一个建立链表的函数,输入每个节点的值,直到这个值是-1的时候函数结束。
在这个里面,我以前一直搞不明白为什么需要定义三个Node *,现在终于了解了,最终还是复习了指针的内容明白的,这里说一下指针实现链表对指针的操作很频繁,需要比较扎实的掌握了指针之后,在来看链表会轻松很多。
在下面的一段程序里,我分别定义了head/p/tmp这三个指向节点结构体的指针,head的主要作用就像一个传销头目,他会主动联系上一个下线p,然后他就什么也不干了,p 接着去发展一个又一个的下线tmp,结果一串以head为首的链表就出来了。
起先,我总觉得有了head,为什么还要p,这是因为如果直接使用head去指向下一个节点,head的位置也是不断在移动的,即它永远处于链表的尾端,这样当我们返回链表的时候,其实是空值。
所以,我们需要p这个中转环节。
(其实,这种做法在指针中非常普遍,大部分有返回指针类型的函数中,都会首先定义一个指针变量来保存函数的传入的参数,而不是对参数直接进行操作)。
/*函数功能:创建一个链表函数描述:每次输入一个新的整数,即把新增加一个节点存放该整数,当输入的整数为-1时,函数结束。
*/List create(){int n=0;Position p,head,tmp;head=NULL;tmp=malloc(sizeof(struct Node));if(tmp==NULL){printf("tmp malloc failed! ");return NULL;}else{p=tmp;printf("please input the first node's message! ");scanf("%d",&(tmp->Value));}while(tmp->Value!=-1){n+=1;if(n==1){head=p;tmp->Next=NULL;}else{p->Next=tmp;}p=tmp;tmp=malloc(sizeof(struct Node));printf("please input the %d node! ",n+1);scanf("%d",&(tmp->Value));}p->Next=NULL;free(tmp); //free函数free掉的只是申请的空间,但是指针还是依然存在的。
tmp=NULL;return head;}接下来,在写一个删除链表节点的函数,输入一个整数然后遍历链表节点,当链表节点的值与该整数相等的时候,即把该节点删除。
在完成这个函数首先一定要把这个过程思考清楚,不可否认我之前是一个上来就敲代码的人,看了《剑指offer》感觉这种习惯是程序员的大忌,甚至还想写一篇博客,名字都想好了《程序员的自我修养之思考在前,代码在后》。
其实想想也是,我们写程序的目的是为了解决问题,而不是为了简单的写程序,纯粹的让程序跑起来大概只会在上学那会存在吧!真实的程序开发中需要考虑几乎所有能想到的实际问题,所以无论程序再下,一要学会先思考清楚,再下笔写程序。
关于这个函数,我们要想到的是:1 如果链表为空,我们该怎么做,当然是直接返回。
2 如果要删除的元素为头节点该怎么办?3 如果要删除的元素为尾节点该怎么办?当注意到以上三个部分,我们的程序就可能避免掉了输入链表为空,程序直接崩溃的现象,也可以避免删除元素值为头节点时删不掉的尴尬。
我们的程序就有了一定的鲁棒性。
下面着重考虑链表的删除的实现:list: Node_a->Node_b->Node_c->Node_d;list tmp?? p-------> ?????? ? ? ? tmp->Next=p->Next;list: Node_a->Node_b----------->Node_dfree(p)假设我们要删除的节点为上图的Node_c;假设我们能够找到Node_c的前一个位置tmp和被删除节点位置p的话;这个时候我们只需要执行tmp->Next=p->Next即可。
只要完成上面的分析以及考虑到各种情况,我们完成下面的代码就水到渠成了。
/*函数功能:删除链表中指定值的节点(如果存在多个,只删除第一个)本例中输入一个整数,删除链表节点值为这个整数的节点。
*/List DeleteNode(List list){Position p,tmp;int value;if(list==NULL){printf("The list is null,function return! ");return NULL;}elseprintf("please input the Node's value: "); scanf("%d",&value);}p=list;if(p->Value==value){list=p->Next;free(p);p=NULL;return list;}while(p!=NULL&&p->Value!=value) {tmp=p;p=p->Next;}if(p->Value==value){if(p->Next!=NULL){tmp->Next=p->Next;}else{tmp->Next=NULL;}free(p);p=NULL;}return list;关于链表的使用场景分析:链表在程序开发中用到的频率还是非常高的,所以在高级语言中往往会对链表进行一些实现,比如STL中list以及Java中也有类似的东西。
在目前的服务器端开发,主要运用链表来接收一些从数据中取出来的数据进行处理。
即使你不知道链表的底层实现,仍然可以成功的运用STL里面的现成的东西。
但是作为一个学习者,我觉得会使用和从底层掌握仍然是两个不同的概念,linux之父说:“talk is less,show you code”。
以下的程序,用链表模拟了一个电话通讯录的功能,包括添加联系人,查找联系人,以及删除联系人。
PS:关于鲁棒性,程序中最大的危险是使用了gets这个函数,目前先保留使用gets,等待找到工作之后在做进一步的程序完善。
(尼玛,读书去。
应届生,找个工作他妈咋这么难呢!?? 工作经验,工作经验,艹,那个大牛一出校门就什么都会。
)/************************************************************** ************Programe:This is a phone list write by listThe programe is just prictise for listAuthor: heat nanMail:****************Data:2015/07/27*************************************************************** ***********/#include#include#include#define N 25#define M 15struct node;typedef struct node* p_node;typedef p_node List;typedef p_node Position;typedef struct node** PList;struct node{char name[N];char number[M];Position next;};int JudgeNameExist(List list,char* name);void AddPerson(PList list);void PrintList(List list);List FindPerson(List list);List FindPersonByName(List list,char* name); int AddPersonByName(PList list,List node);int DeletePersonByName(PList list,char* name); void DeletePerson(PList list);int main(){List list=NULL;Position p;char cmd[100];while(1){printf(" MAIN ");printf(" ******* 1 add a person ******* "); printf(" ******* 2 show the phone list ******* "); printf(" ******* 3 find from phone list ******* ");printf(" ******* 4 from phone list ******* ");printf("Please input the cmd number: ");gets(cmd);switch(cmd[0]){case '1':AddPerson(&list);break;case '2':PrintList(list);break;case '3':FindPerson(list);break;case '4':DeletePerson(&list);break;default:printf("wrong cmd! ");break;}}return 0;}/*Function:判断要添加的联系人名称是否已经存在于电话簿中. Input: List 电话列表,name 要添加的联系人的姓名. Return: 已经存在返回1,不存在返回0.*/int JudgeNameExist(List list,char* name){if(FindPersonByName(list,name)!=NULL) return 1;elsereturn 0;}/*Function:根据输入的姓名查找联系人的信息节点Input: 要输入的电话列表list,姓名name Return: 返回查找到的节点*/List FindPersonByName(List list,char* name) {while(list!=NULL){if(strcmp(list->name,name)==0)break;list=list->next;}return list;}/*Function:根据姓名添加新的联系人到联系人列表Input: 指向联系人列表地址的指针,新用户节点Return: 添加成功返回1,添加失败返回0*/int AddPersonByName(PList list,List node) {if(node==NULL){printf("the node is NULL! ");return 0;}if(*list==NULL){*list=node;return 1;}List pHead=*list;while(pHead->next!=NULL)pHead=pHead->next;pHead->next=node;return 1;}void AddPerson(PList list){Position tmp;Position p_head;tmp=(struct node*)malloc(sizeof(struct node));char name[N];char number[M];if(tmp==NULL){printf("malloc the tmp node failed in function add person! "); }else{printf("please input the name: ");gets(name);printf("please input the number: ");gets(number);strcpy(tmp->name,name);strcpy(tmp->number,number);tmp->next=NULL;}if(JudgeNameExist(*list,name)==1){free(tmp);printf("the name have already exist! ");return;}AddPersonByName(list,tmp);}/*Function: 打印联系人列表Input:联系人列表*/void PrintList(List list){Position show;show=list;if(show==NULL){return ;}printf("Now,we print the phone list: ");while(show!=NULL){printf("Name:%s Number:%s ",show->name,show->number);show=show->next;}}List FindPerson(List list){char name[N];Position pHead=list;printf("please input the name you will find: ");gets(name);Position node=FindPersonByName(list,name);if(node!=NULL)printf("find success! name-> %s number-> %s ",node->name,node->number);elseprintf("find failed! ");return node;}/*Function:根据姓名删除联系人Input:指向联系人地址的指针,联系人姓名Output:删除成功返回1,失败返回0*/int DeletePersonByName(PList list,char* name){if(*list==NULL||name==NULL)return 0;List pHead=*list;if(strcmp(pHead->name,name)==0){*list=pHead->next;free(pHead);pHead->next==NULL;return 0;}List tmp=pHead->next;while(tmp!=NULL){if(strcmp(tmp->name,name)==0){pHead->next=tmp->next;free(tmp);tmp->next=NULL;return 1;}pHead=tmp;tmp=tmp->next;}return 0;}void DeletePerson(PList list){List pHead=*list;if(pHead==NULL){printf("there is no person you can delet "); return ;}char name[N];printf("please input the name: ");gets(name);DeletePersonByName(list,name); }【c语言链表的用法】。