赞
踩
链表是一种数据结构,所谓的数据结构就是数据存放的思想。类似数组但又不是数组,比数组更加灵活好用,可以存放许多不同类型的数据。
例如 我们定义一个存放10个元素的整形数组 int arry[10] ,我们对数组的 ‘查’ 和 ’改‘ 很方便,但是对数组的 增加 和 删除 却很难。数组已经定死了10个元素。数组是连续的空间,此时想要在数组中增加其中一个元素或删除一个元素很难。另外数组只能存放指定类型的数据(例如 int数组只能存放int类型数据 ,char数组 只能存放char类型数据),不能同时存放多种类型、复杂的数据,不灵活不方便。
链表这个数据结构能够很好的解决以上这些问题。
a、数组中数的类型必须相同;
b、数组中数在内存中必须是连续存储的,链表是不连续的地址空间
c、 链表可以在节点中定义多种数据类型,数组只能定义一种类型,数据类型单一
- struct Test //这是结构体 链表节点的
- {
- int x,y,z;
- float a,b,c;
- char i,j;
- int num [20];
- char arry[10] = {0}; //链表的成员变量,一个节点存放数据,
- //k可以根据自己的需求,在节点中定义多种数据类型;
-
- struct Test *next; //链表节点的连接,这是链表连接的关键,存放下一个节点的地址
- }; //存放下一个节点的地址可以访问下一个节点的数据
代码如下
- #include<stdio.h>
- #include<stdlib.h>
- struct Test //结构体的成员变量
- {
- int data;
- struct Test *next;
- };
-
- void Test(struct Test *head) //遍历链表中所有的节点,打印出链表节点的值data
- {
- while(head != NULL){
-
- printf("%d ",head->data);
- head = head->next;
- }
-
- putchar('\n');
- }
-
- int cha(struct Test *head,int number) //查找链表中是否存在这个值
- {
-
- while(head != NULL){
-
- if(head->data == number){ //判断是否存在我们想要查找的这个值
- printf("find Test data = %d,number = %d \n",head->data,number);
- return 1; //查找成功打印提示信息,并返回return 1。
- }
-
- head = head->next;
- }
-
-
- return -1; //查找失败返回-1
- }
-
- int gai(struct Test *head,int number ,int data) //调用此函数,修改链表中的值
- {
- while(head != NULL){ //遍历链表
-
- if(head->data == number){ //判断链表节点是否存在这个值,存在就修改这个节点的值
- head->data = data;
- return 1; //修改成功返回1
- }
-
- head = head->next;
- }
-
-
- return 0; //修改失败返回0
- }
- int main()
- {
- struct Test *head = NULL;
- int number;
- int data;
- struct Test t1; //结构体链表节点的定义
- struct Test t2; //定义五个节点 t1、t2、t3、t4、t5
- struct Test t3;
- struct Test t4;
- struct Test t5;
-
- t1.data = 100; //给五个节点赋值和结构体链表节点的连接
- t1.next = &t2;
- t2.data = 200;
- t2.next = &t3;
- t3.data = 300;
- t3.next = &t4;
- t4.data = 400;
- t4.next = &t5;
- t5.data = 500;
- t5.next = NULL;
-
- head = &t1; //结构体链表的头节点赋值
-
- puts("please scanf number");
- scanf("%d",&number); //请输入需要查链表节点中的值,值存放在number变量
-
- if(cha(head,number) == -1){ //调用int cha(struct Test *,int)传入链表头结点
- puts("Not find number"); //head和需要查找的值number。如果查找失败打印提示
- Test(head); //打印链表中的所有的值,并且调用exit退出程序运行。
- exit(-1);
- }
-
- Test(head); //遍历打印链表所有的值
-
- puts("please enter amend data");
- scanf("%d",&data); //输入修改的新值data
-
- gai(head,number,data); //把找到链表节点中的值number,修改成新的值data
-
- Test(head);
-
- return 0;
- }
- ~
- ~
- ~
运行结果:
- please scanf number //提示 输入需要查找的值
- 300 //输入 300
- find Test data = 300,number = 300 //成功查找到300这个值
- 100 200 300 400 500 //打印链表节点的数据,显示300 值的位置
- please enter amend data //提示 输入需要修的值
- 888 //输入888
- 100 200 888 400 500 //把链表节点300值成功修改成888 ,打印所有链表结果
代码如下
- #include<stdio.h>
- struct Test
- {
- int data;
- struct Test *next;
- };
-
- struct Test *delete(struct Test *head,int number) //delete删除节点函数
- {
- struct Test *p = head;
-
- if(head == NULL ){ //判断链表是否存在
- puts(" inexistence head == NULL");
- return NULL;
- }
- if(head->data == number){ //先判断链表第一个节点是否需要删除
- p = head->next; //如果需要删除,就把第一节点的下一个节点,作为新的第一节点
- return p; //返回新的头节点
- }
-
- while(head->next != NULL){ //遍历链表节点
-
- if(head->next->data == number){ //判断,如果当前这个节点的下一个节点的值是我
- //们需要删除的节点时
-
- head->next = head->next->next; // 把当前节点连接,改为下一个节点的一下一个节点
- return p; //删除成功返回头节点
- }
-
- head = head->next;
- }
-
- puts("not find"); //删除失败 打印提示信息
-
- return p; //删除失败 并返回头节点
- }
-
- void Test(struct Test *head) //遍历打印所有链表节点的值,
- {
- while(head != NULL){
-
- printf("%d ",head->data);
- head = head->next;
- }
-
- putchar('\n');
- }
-
- int main()
- {
- int number;
- struct Test *head = NULL;
-
- struct Test t1,t2,t3,t4,t5; //定义五个链表节点t1,t2,t3,t4,t5
-
- t1.data = 100; //给五个链表节点赋值和连接
- t1.next = &t2;
- t2.data = 200;
- t2.next = &t3;
- t3.data = 300;
- t3.next = &t4;
- t4.data = 400;
- t4.next = &t5;
- t5.data = 500;
- t5.next = NULL;
-
- head = &t1; //链表头节点 (第一个节点)
-
- Test(head); //遍历打印所有链表节点的值
-
- puts("please scanf number");
- scanf("%d",&number); //输入需要删除节点的值
-
- head = delete(head,number); //调用delete()函数查找链表节点需要删除的值,并删除节点
-
- Test(head); //遍历打印所有链表节点的值,查看删除链表结果
-
- return 0;
- }
- ~
- ~
- ~
- ~
- ~
运行结果:
- ./a.out //执行程序
- 100 200 300 400 500 //遍历打印链表所有节点的值
- please scanf number //提示输入需要删除节点的值
- 400 //输入400
- 100 200 300 500 //遍历打印链表所有节点的值,链表节点400被删除
有两种插入方式:1、节点后面插入 2、节点前面插入
1、节点后面插入
- #include<stdio.h>
- #include<stdlib.h>
- struct Test
- {
- int data;
- struct Test *next;
- };
-
- void Test(struct Test *head)
- {
- while(head != NULL){
-
- printf("%d ",head->data);
- head = head->next;
- }
-
- putchar('\n');
- }
- struct Test *weicha(struct Test *head,int number) //链表节点后面插入
- {
- struct Test *hp = head; //保留链表头节点(链表的第一节点)
-
- struct Test *p; //创建新的节点
- p = (struct Test *)malloc( sizeof(struct Test) ); //给新节点开辟空间
- puts("scanf *p data"); //给新节点赋值
- scanf("%d",&p->data);
-
- while(head != NULL){ //遍历链表所有节点
-
- if(head->data == number){ //判断此节点是的值,是不是我们要插入新节点的节点的值
- p->next = head->next; //节点的向后插入新的节点
- head->next = p;
- return hp; //插入成功,返回头节点
- }
- head = head->next;
- }
-
- puts("Not find number"); //插入失败打印提示信息
- return hp;
- }
- int main()
- {
- int number;
- struct Test *head = NULL;
-
- struct Test t1,t2,t3,t4,t5; //定义五个新节点,t1,t2,t3,t4,t5
-
- t1.data = 100; //五个链表节点的连接赋值
- t1.next = &t2;
- t2.data = 200;
- t2.next = &t3;
- t3.data = 300;
- t3.next = &t4;
- t4.data = 400;
- t4.next = &t5;
- t5.data = 500;
- t5.next = NULL;
-
- head = &t1; //链表的头节点(第一节点)
-
- Test(head); //遍历打印所有节点
-
- while(1){ //输入0退出循环,否者不断进行链表新节点的插入
- puts("please number");
- scanf("%d",&number); //输入你需要在那个节点后插入新的节点
- if(number == 0){ //输入0退出循环,否者不断进行链表新节点的插入
- break;
- }
- weicha(head,number); //调用函数,
- Test(head); //打印修改结果
- }
-
- Test(head);
- return 0;
- }
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
运行结果:
- 100 200 300 400 500 //遍历打印链表节点所有的值
- please number //提示输入。 在哪个链表节点后面插入新的链表节点
- 100 //输入100。 选择在100链表节点后面插入新节点
- scanf *p data //提示输入。 请输入在链表100后插入多少的值
- 101 //输入101。 在100后面插入101的值
- 100 101 200 300 400 500 //打印链表节点的修改结果 100节点后面插入新的节点101 ,插入修改成功
- please number //以下步骤,同上
- 500
- scanf *p data
- 501
- 100 101 200 300 400 500 501
- please number //以下步骤,同上
- 300
- scanf *p data
- 301
- 100 101 200 300 301 400 500 501
- please number //以下步骤,同上
- 0 //输入0 结束向后插入新的节点操作
- 100 101 200 300 301 400 500 501 //遍历打印最终链表插入修改的结果
2、节点前面插入
- #include<stdio.h>
- #include<stdlib.h>
- struct Test
- {
- int data;
- struct Test *next;
- };
-
- void Test(struct Test *head)
- {
- while(head != NULL){
-
- printf("%d ",head->data);
- head = head->next;
- }
-
- putchar('\n');
- }
- struct Test *toucha(struct Test *head,int number) //向链表节点的前面插入新的节点
- {
- struct Test *head2 = head;
-
- struct Test *p; //创建新的链表节点
- p = (struct Test *)malloc( sizeof(struct Test) ); //为新节点开辟新的空间
- puts("scanf *p data");
- scanf("%d",&p->data); 输入新节点的data值
-
- if(head->data == number){ //首先判断是否选择在链表头节点(第一个节点)前面插入新节点
- p->next = head; //如果是,就把新的节点作为新头节点,连接上旧的头节点
- return p; //返回新的头节点
- }
-
- while(head->next != NULL){ //链表节点的遍历,从链表的第二个节点开始遍历,头节点前面已经判断过了
-
- if(head->next->data == number){ //判断当前链表节点的下一个链表节点是不是我想要向前插入的
- p->next = head->next;
- head->next = p;
- return head2;
- }
- head = head->next;
- }
-
- puts("Not find number"); //查找输出失败打印提示信息
- return head2;
- }
- int main()
- {
- int number;
- struct Test *head = NULL;
-
- struct Test t1,t2,t3,t4,t5; //链表节点的定义
-
- t1.data = 100; //链表节点的赋值和连接
- t1.next = &t2;
- t2.data = 200;
- t2.next = &t3;
- t3.data = 300;
- t3.next = &t4;
- t4.data = 400;
- t4.next = &t5;
- t5.data = 500;
- t5.next = NULL;
-
- head = &t1; // 链表的头节点
-
- Test(head); //遍历所有链表的节点,打印
-
- while(1){
- puts("please number"); //提示信息,输入你要向前插入节点的位置
- scanf("%d",&number);
- if(number == 0){ //输入为0,退出插入循环
- break;
- }
- head = toucha(head,number);
- Test(head); //插入一次打印一遍链表,查看插入结果
- }
-
- Test(head); //打印链表最终结果
- return 0;
- }
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
- ~
运行结果:
- 100 200 300 400 500 //打印链表所有节点
- please number //提示输入,需要在那个节点前插入一个新的节点
- 500 //输入500 ,在节点链表500前插入
- scanf *p data //提示输入,在500前面插入的值为多少
- 499 //输入499 ,在500链表节点前插入新的节点 499
- 100 200 300 400 499 500 // 插入新链表节点成功,打印链表。在500 前插入499
- please number //以下步骤,同上
- 100
- scanf *p data
- 99
- 99 100 200 300 400 499 500
- please number //以下步骤,同上
- 300
- scanf *p data
- 299
- 99 100 200 299 300 400 499 500
- please number //输入为0退出循环,结束向前插入新的节点操作
- 0
- 99 100 200 299 300 400 499 500 //打印所有链表节点,最终结果。
创建链表节点分为 1.尾插法 2.头插法
- #include<stdio.h>
- #include<stdlib.h>
- struct Test
- {
- int data;
- struct Test *next;
- };
-
- void printLink(struct Test *head) //遍历打印所有链表节点
- {
- while(head != NULL){
-
- printf("%d ",head->data);
- head = head->next;
- }
-
- putchar('\n');
- }
-
- struct Test *endInsert(struct Test *head,struct Test *new) //尾插法,向后插入新的节点
- {
- struct Test *p = head;
-
- if(head == NULL){ //判断链表节点是否为空
- head = new; //如果是空的链表头节点,让头节点=新节点
- return head; //返回头节点地址
- }
-
- while(head->next != NULL){ //如果链表头节点不为空NULL,
-
- head = head->next; //遍历链表节点,使指针 位移到链表的最后一个节点,
- }
-
- head->next = new; //最后一个节点,连接到下一个新节点的地址,
-
- return p; //返回头节点地址
- }
-
- struct Test *createLink(struct Test *head) //动态创建链表
- {
- struct Test *new = NULL; //链表新节点的定义
-
- while(1){
- new =(struct Test *)malloc(sizeof(struct Test) ); //给链表新节点开辟新空间
- new->next = NULL;
- puts("createLink new data"); //给链表新节点data赋值
- scanf("%d", &(new->data) );
-
- if(new->data == 0){ //data输入为0时,停止链表节点的创建退出
- free(new); //清除不需要的新节点空间,堆
- puts("Quit"); //打印退出提示信息
- return head; //返回链表头节点地址
- }
-
- head = endInsert(head,new); //每创建一次新的链表节点,就调用endInsert()函数
- //让新的节点插入链表最后一位节点
- }
-
- return head;
- }
-
- int main()
- {
- int number;
- struct Test *head = NULL;
-
- head = createLink(head); //不断动态创建链表,并且吧创建新的的链表节点插在链表的最后一位
-
- struct Test t1 = {888,NULL}; //单独创建一个新的节点
-
- head = endInsert(head,&t1); //创建一个新节点t1,放在链表最后一位,单独调用endInsert函数
-
- printLink(head); //打印所有链表节点,看最终结果
-
-
-
- return 0;
- }
运行结果:
- createLink new data //提示输入 ,创建的节点,为新的节点赋值值
- 1 //输入1,节点的值为1
- createLink new data //创建第二个节点
- 2
- createLink new data //创建第三个节点
- 3
- createLink new data //创建第四个节点
- 4
- createLink new data //创建第五个节点
- 5
- createLink new data //输入为0,取消节点的创建
- 0
- Quit //退出创建
- 1 2 3 4 5 888 //打印链表节点的结果
- //为何最后一个节点是888,因为单独创建一个新节点 struct Test t1
- #include<stdio.h>
- #include<stdlib.h>
- struct Test
- {
- int data;
- struct Test *next;
- };
-
- void printLink(struct Test *head)
- {
- while(head != NULL){
-
- printf("%d ",head->data);
- head = head->next;
- }
-
- putchar('\n');
- }
-
- struct Test *headInsert(struct Test *head,struct Test *new) //链表节点的头插法,向链表头节点插入一个新的节点
- {
-
- if(head == NULL){ //判断头节点是否为空指针NULL
- head = new; //是,就让新节点作为头节点
- return head; //返回头节点
-
- }else{
- new->next = head; //如果头节点不为空,就让新的节点连接下一个旧的链表头节点
- head = new; //(吧旧的头节点作为第二个节点,新的节点作为第一个节点(头节点))
- }
-
- return head;
- }
-
- struct Test *createLink(struct Test *head)//不断动态创建新的节点,并且吧新节点,作为新的头节点
- {
- struct Test *new = NULL; //新节点的定义
-
- while(1){
- new =(struct Test *)malloc(sizeof(struct Test) ); //为新节点开辟新空间
- new->next = NULL;
- puts("createLink new data"); //为新节点赋值
- scanf("%d", &(new->data) );
-
- if(new->data == 0){ //当不需要创建新节点的时候,输入0,退出创建节点
- free(new);
- puts("Quit"); //打印提示信息
- return head; //返回链表头节点
- }
-
- head = headInsert(head,new); //每创建一次新的节点,就把新的节点,作为新的链表头节点(头插法)
-
- }
-
- return head;
- }
-
- int main()
- {
- int number;
- struct Test *head = NULL;
-
- head = createLink(head); //调用createLink()函数不断创建新节点,并且吧新的节点作为新的头节点(头插法)
-
- printLink(head); //打印链表节点结果
-
- struct Test t1 = {888,NULL}; //单独创建新的节点
- head = headInsert(head,&t1); //单独调用headInsert()函数(头插法), 吧t1插入头节点
-
- printLink(head); //打印最终链表结果
-
-
-
- return 0;
- }
运行结果:
- ./a.out //运行程序
- createLink new data //动态创建新节点,并把新的节点作为头节点(头插法)
- 1 //输入1,输入新节点的值为1
- createLink new data //以下步骤,同上
- 2
- createLink new data //以下步骤,同上
- 3
- createLink new data //以下步骤,同上
- 4
- createLink new data //以下步骤,同上
- 5
- createLink new data //输入为0 ,停止创建链表新节点,退出
- 0
- Quit //打印退出提示信息
- 5 4 3 2 1 //打印用头插法动态创建链表节点的结果
- 888 5 4 3 2 1 //在单独调用endInsert()函数插入一个新节点888
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。