• c语言提高学习笔记——02-c提高06day


    在学习c语言提高总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    02-c提高06day

    目录:
    一、函数指针
    1、函数类型
    2、函数指针(指向函数的指针)
    3、函数指针数组
    4、函数指针做函数参数(回调函数)
    二、链表
    1、链表基本概念
    (1)什么是链表
    (2)有关结构体的自身引用
    (3)链表节点
    (4)链表的分类
    1)静态链表
    2)动态链表
    3)带头和不带头链表
    4)单向链表、双向链表、循环链表
    2、链表基本操作
    (1)创建链表
    (2)遍历链表
    (3)插入节点
    (4)删除节点
    (5)销毁链表
    练习:链表的操作

    一、函数指针

    1、函数类型
    通过什么来区分两个不同的函数?

    一个函数在编译时被分配一个入口地址,这个地址就称为函数的指针,函数名代表函数的入口地址。

    函数三要素:名称、参数、返回值。C语言中的函数有自己特定的类型。

    c语言中通过typedef为函数类型重命名:

    1 typedef int f(int,int);//f为函数类型
    2 typedef void p(int);//p为函数类型

    这一点和数组一样,因此我们可以用一个指针变量来存放这个入口地址,然后通过该指针变量调用函数。

    注意:通过函数类型定义的变量是不能够直接执行,因为没有函数体。只能通过类型定义一个函数指针指向某一个具体函数,才能调用。

     1 typedef int(p)(int,int);
     2 
     3 void my_func(int a,int b){
     4     printf("%d %d
    ",a,b);
     5 }
     6 void test(){
     7 
     8     p pl;
     9     //pl(10,20);//错误,不能直接调用,只描述了函数类型,但是并没有定义函数体,没有函数体无法调用
    10     p* p2=my_func;
    11     p2(1020);//正确,指向有函数体的函数入口地址
    12 }

    2、函数指针(指向函数的指针)

    ■函数指针定义方式(先定义函数类型,根据类型定义指针变量);

    ■先定义函数指针类型,根据类型定义指针变量;

    ■直接定义函数指针变量;

     1 int my_func(int a,int b){
     2     printf("ret:%d
    ",a+b);
     3     return 0;
     4 }
     5 
     6 //1.先定义函数类型,通过类型定义指针
     7 void test01(){
     8     typedef int(FUNC_TYPE)(int,int);
     9     FUNC_TYPE*f=my_func;
    10     //如何调用?
    11     (*f)(10,20);
    12     f(10,20);
    13 }
    14 
    15 //2.定义函数指针类型
    16 void test02(){
    17     typedef int(*FUNC_POINTER)(int,int);
    18     FUNC_POINTERf=my_func;
    19     //如何调用?
    20     (*f)(10,20);
    21     f(10,20);
    22 }
    23 
    24 //3.直接定义函数指针变量
    25 void test03(){
    26     int(*f)(int,int)=my_func;
    27     //如何调用?
    28     (*f)(10,20);
    29     f(10,20);
    30 }

    3、函数指针数组

    函数指针数组,每个元素都是函数指针。

     1 void func0l(int a){
     2     printf("func01:%d
    ",a);
     3 }
     4 void func02(int a){
     5     printf("func02:%d
    ",a);
     6 }
     7 void func03(int a){
     8     printf("func03:%d
    ",a);
     9 }
    10 void test(){
    11 #if 0
    12     //定义函数指针
    13     void(*func_array[])(int)={func01,func02,func03};
    14 #else
    15     void(*func_array[3])(int);
    16     func_array[0]=func01;
    17     func_array[1]=func02;
    18     func_array[2]=func03;
    19 #endif
    20 
    21     for(int i=0;i<3;i++){
    22         func_array[i](10+i);
    23         (*func_array[i])(10+i);
    24     }
    25 }

    4、函数指针做函数参数(回调函数)

    函数参数除了是普通变量,还可以是函数指针变量。

    1 //形参为普通变量
    2 void fun(int x){}
    3 //形参为函数指针变量
    4 void fun(int(*p)(int a)){}

    函数指针变量常见的用途之一是把指针作为参数传递到其他函数指向函数的指针也可以作为参数,以实现函数地址的传递。

     1 //加法计算器
     2 int plus(int a,int b){
     3     return a+b;
     4 }
     5 
     6 //减法计算器
     7 int minus(int a,int b){
     8     return a-b;
     9 }
    10 
    11 //计算器
    12 #if 0
    13 int caculator(int a,int b,int(*func)(int,int)){
    14     return func(a,b);
    15 }
    16 #else
    17 typedef int(*FUNC_POINTER)(int,int);
    18 int caculator(int a,int b,FUNC_POINTER func){
    19     return func(a,b);
    20 }
    21 #endif

    注意:函数指针和指针函数的区别:

    ■函数指针是指向函数的指针;

    ■指针函数是返回类型为指针的函数;

    练习1:如何定义函数指针?

     函数名起始就是函数的入口地址

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 
     6 //决定函数的类型应该是:函数的返回值 函数的参数列表
     7 
     8 
     9 void func()
    10 {
    11     printf("hello world!");
    12 }
    13 
    14 //func函数名起始是代表函数的入口地址
    15 
    16 //如何定义一个指向函数的指针?
    17 int myfunc(int a, char b)
    18 {
    19     printf("int myfunc(int a, char b)!");
    20     return 0;
    21 }
    22 void test01()
    23 {
    24     //1.定义函数类型,通过类型来定义函数指针(定义不加*,使用加/不加*都行)
    25     typedef int(FUN_TYPE)(int ,char);
    26     FUN_TYPE* pFunc = myfunc;
    27     
    28     pFunc(10, 'a');
    29     (*pFunc)(20, 'b');//调用的两种方式
    30     myfunc(30, 'c');
    31     
    32     //2.直接定义函数指针类型(定义加*,使用不加*)
    33     typedef int(*FUNC_P)(int, char);
    34     FUNC_P pFunc2 = myfunc;
    35     pFunc2(20, 'd');
    36     
    37     //函数指针指向同类型
    38     //pFunc2 = func;
    39     
    40     //3.直接定义函数指针变量,函数指针的类型是:int(*)(int, char)
    41     //把指针转换为函数指针类型写法int(*pFunc3)(int, char) = int(*)(int, char) NULL;
    42     int(*pFunc3)(int, char) = NULL;
    43     pFunc3 = myfunc;
    44     pFunc3(50, 'p');
    45     
    46     printf("pFunc3 size:%d
    ", sizeof(pFunc3));
    47 }
    48 
    49 
    50 
    51 int main(){
    52 
    53     test01();
    54     
    55     system("pause");
    56     return EXIT_SUCCESS;
    57 }

    练习2:函数指针做函数式参数

      1 #define _CRT_SECURE_NO_WARNINGS
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<stdlib.h>
      5 
      6 int con1(int a, int b)
      7 {
      8     return a + b;
      9 }
     10 
     11 int con2(int a, int b)
     12 {
     13     return a + b + 10;
     14 }
     15 
     16 int con3(int a, int b)
     17 {
     18     return a + b - 10;
     19 }
     20 
     21 int con4(int a, int b)
     22 {
     23     return a * b - 10;
     24 }
     25 
     26 int con5(int a, int b)//直接新增加一个规则
     27 {
     28     return a + b - 3 + 100 * 2;
     29 }
     30 
     31 void test01()
     32 {
     33     int(*pFunc)(int, int) = con1;//con1可以直接改为con2、con3、con4
     34     int ret = pFunc(10, 20);
     35     printf("ret = %d
    ", ret);
     36 }
     37 
     38 //1.函数可以做另外一个函数的参数(定制)
     39 void doLogic(int(*pFunc)(int, int))
     40 {
     41     int a = 10;
     42     int b = 20;
     43     int ret = pFunc(a, b);
     44     printf("ret = %d
    ", ret);
     45 }
     46 void test02()
     47 {
     48     doLogic(con1);
     49 }
     50 
     51 //2.函数指针数组
     52 void fun1()
     53 {
     54     printf("fun1
    ");
     55 }
     56 void fun2()
     57 {
     58     printf("fun2
    ");
     59 }
     60 void fun3()
     61 {
     62     printf("fun3
    ");
     63 }
     64 void test03()
     65 {
     66     void(*func_array[3])();
     67     func_array[0] = fun1;
     68     func_array[1] = fun2;
     69     func_array[2] = fun3;
     70     
     71     for(int i = 0; i < 3; ++i)
     72     {
     73         func_array[i]();
     74     }
     75     
     76 }
     77 
     78 //函数指针做函数参数(回调函数)
     79 void printAllArray(void* arr, int eleSize, int len, void(*print)(void*))
     80 {
     81     char* start = (char*)arr;
     82     for(int i = 0; i < len; ++i)
     83     {
     84         //printf("%d
    ", start + i * eleSize);//测试地址
     85         char* eleAddr = start + i * eleSize;
     86         print(eleAddr);
     87     }
     88 }
     89 
     90 void MyPrint(void* data)
     91 {
     92     int* p = (int*)data;
     93     printf("%d ", *p);
     94 }
     95 
     96 struct Person
     97 {
     98     char name[64];
     99     int age;
    100 };
    101 
    102 void MyPrintPerson(void* data)
    103 {
    104     struct Person* person = (struct Person*)data;
    105     printf("Name:%s Age:%d
    ", person->name, person->age);
    106 }
    107 
    108 void test04()
    109 {
    110     int arr[] = {1, 2, 3, 4, 5};
    111     printAllArray(arr, sizeof(int), 5, MyPrint);
    112     //printf("---------------");
    113     //for(int i = 0; i < 5; ++i)
    114     //{
    115     //    printf("%d
    ", &arr[i]);//测试地址
    116     //}
    117     
    118     struct Person persons[] = {
    119         {"aaa", 10};
    120         {"bbb", 20};
    121         {"ccc", 30};
    122         {"ddd", 40};
    123         {"eee", 50};
    124     };
    125     printAllArray(persons, sizeof(struct Person), 5, MyPrintPerson);
    126 }
    127 
    128 
    129 int main(){
    130 
    131     //test01();
    132     //test02();
    133     //test03();
    134     test04();
    135     
    136     system("pause");
    137     return EXIT_SUCCESS;
    138 }

    二、链表

    1、链表基本概念
    (1)什么是链表

    ·链表是一种常用的数据结构,它通过指针将一些列数据结点,连接成一个数据链。相对于数组,链表具有更好的动态性(非顺序存储)。
    ·数据域用来存储数据,指针域用于建立与下一个结点的联系。
    ·建立链表时无需预先知道数据总量的,可以随机的分配空间,可以高效的在链表中的任意位置实时插入或删除数据。
    ·链表的开销,主要是访问顺序性和组织链的空间损失。

    数组和链表的区别?

    数组:一次性分配一块连续的存储区域。
    优点:随机访问元素效率高
    缺点:1)需要分配一块连续的存储区域(很大区域,有可能分配失败)
    2)删除和插入某个元素效率低

    链表:无需一次性分配一块连续的存储区域,只需分配n块节点存储区域,通过指针建立关系。
    优点:1)不需要一块连续的存储区域
    2)删除和插入某个元素效率高
    缺点:随机访问元素效率低

    (2)有关结构体的自身引用

    问题1:请问结构体可以嵌套本类型的结构体变量吗?

    问题2:请问结构体可以嵌套本类型的结构体指针变量吗?

     1 typedef struct _STUDENT{
     2     char name[64];
     3     int age;
     4 }Student;
     5 
     6 typedef struct _TEACHER{
     7     char name[64];
     8     Student stu;//结构体可以嵌套其他类型的结构体
     9     //Teacher stu;
    10     //struct _TEACHER teacher;/此时Teacher类型的成员还没有确定,编译器无法分配内存
    11     struct _TEACHER* teacher;/不论什么类型的指针,都只占4个字节,编译器可确定内存分配
    12 }Teacher;


    ■结构体可以嵌套另外一个结构体的任何类型变量;
    ■结构体嵌套本结构体普通变量(不可以)。本结构体的类型大小无法确定,类型本质:固定大小内存块别名;
    ■结构体嵌套本结构体指针变量(可以),指针变量的空间能确定,32位,4字节,64位,8字节;

    (3)链表节点
    大家思考一下,我们说链表是由一系列的节点组成,那么如何表示一个包含了数据域和指针域的节点呢?

    链表的节点类型实际上是结构体变量,此结构体包含数据域和指针域:
    ·数据域用来存储数据;
    ·指针域用于建立与下一个结点的联系,当此节点为尾节点时,指针域的值为NULL

    1 typedef struct Node
    2 {
    3     //数据域
    4     int id;
    5     char name[50];
    6     //指针域
    7     struct Node *next;
    8 }Node;


    (4)链表的分类
    链表分为:静态链表和动态链表

    静态链表和动态链表是线性表链式存储结构的两种不同的表示方式:
    ·所有结点都是在程序中定义的,不是临时开辟的,也不能用完后释放,这种链表称为“静态链表”。
    ·所谓动态链表,是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。

    1)静态链表

     1 typedef struct Stu
     2 {
     3     int id;//数据域
     4     char name[100];
     5 
     6     struct Stu *next;//指针域
     7 }Stu;
     8 
     9 void test()
    10 {
    11     //初始化三个结构体变量
    12     Stu sl={1,"yuri",NULL};
    13     Stu s2={2,"1ily",NULL};
    14     Stu s3={3,"lilei",NULL};
    15 
    16     s1.next=&s2;//s1的next 指针指向s2
    17     s2.next=&s3;
    18     s3.next=NULL;//尾结点
    19 
    20     Stu* p=&s1;
    21     while(p!=NULL)
    22     {
    23         printf("id=%d,name=%s
    ",p->id,p->name);
    24         //结点往后移动一位
    25         p=p->next;
    26     }
    27 }

    2)动态链表

     1 typedef struct Stu{
     2     int id;//数据域
     3     char name[100];
     4 
     5     struct Stu *next;/指针域
     6 }Stu;
     7 
     8 void test(){
     9     //动态分配3个节点
    10     Stu*s1=(Stu *)malloc(sizeof(Stu));
    11     s1->id=1;
    12     strcpy(s1->name,"yuri");
    13 
    14     Stu*s2=(Stu *)malloc(sizeof(Stu));
    15     s2->id=2;
    16     strcpy(s2->name,"lily");
    17 
    18     Stu*s3=(Stu *)malloc(sizeof(Stu));
    19     s3->id=3;
    20     strcpy(s3->name,"lilei");
    21 
    22     //建立节点的关系
    23     s1->next=s2;//s1的next 指针指向s2
    24     s2->next=s3;
    25     s3->next=NULL;//尾结点
    26 
    27     //遍历节点
    28     Stu*p=s1;
    29     while(p!=NULL)
    30     {
    31         printf("id=%d,name=%s
    ",p->id,p->name);
    32         //结点往后移动一位
    33         p=p->next;
    34     }
    35     //释放节点空间
    36     p=sl;
    37     Stu *tmp=NULL;
    38     while(p!=NULL)
    39     {
    40         tmp=p;
    41         p=p->next;
    42         free(tmp);
    43         tmp=NULL;
    44     }
    45 }

    3)带头和不带头链表
    ·带头链表:固定一个节点作为头结点(数据域不保存有效数据),起一个标志位的作用,以后不管链表节点如果改变,此头结点固定不变

    ·不带头链表:头结点不固定,根据实际需要变换头结点(如在原来头结点前插入新节点,然后,新节点重新作为链表的头结点)。

    4)单向链表、双向链表、循环链表
    单向链表:

    双向链表:

    循环链表:


    2、链表基本操作
    (1)创建链表
    使用结构体定义节点类型:

    1 typedef struct _LINKNODE
    2 {
    3     int id;//数据域
    4     struct LINKNODE* next;/指针域
    5 }link_node;

    编写函数:link_node* init_linklist()
    建立带有头结点的单向链表循环创建结点结点数据域中的数值从键盘输入以-1作为输入结束标志,链表的头结点地址由函数值返回.

     1 typedef struct LINKNODE{
     2     int data;
     3     struct LINKNODE* next;
     4 }1ink_ node;
     5 
     6 1ink node* init_linklist(){
     7 
     8     //创建头结点指针
     9     1ink node* head=NULL;
    10     //给头结点分配内存
    11     head=(link node*)malloc(sizeof(link_node));
    12     if(head==NULL){
    13         return NULL;
    14     }
    15     head->data=-1;
    16     head->next=NULL;
    17 
    18     //保存当前节点
    19     1ink node* p_current=head;
    20     int data=-1;
    21     //循环向链表中插入节点
    22     while(1){
    23 
    24         printf("please input data:
    ");
    25         scanf("%d",&data);
    26 
    27         //如果输入-1,则退出循环
    28         if(data==-1){
    29             break;
    30         }
    31         
    32         //给新节点分配内存
    33         link_node* newnode=(link_node*)malloc(sizeof(link_node));
    34         if(newnode==NULL){
    35             break;
    36         }
    37         
    38         //给节点赋值
    39         newnode->data=data;
    40         newnode->next=NULL;
    41 
    42         //新节点入链表,也就是将节点插入到最后一个节点的下一个位置
    43         p_current->next=newnode;
    44         //更新辅助指针p_current
    45         p_current=newnode;
    46     }
    47     return head;
    48 }

    (2)遍历链表
    编写函数:void foreach_linklist(link_node* head()
    顺序输出单向链表各项结点数据域中的内容:

     1 //遍历链表
     2 void foreach_linklist(link node* head){
     3     if(head==NULL){
     4         return;
     5     }
     6     
     7     //赋值指针变量
     8     1ink node* p_current=head->next;
     9     while(p_current!=NULL){
    10         printf("%d",p_current->data);
    11         p_current=p_current->next;
    12     }
    13     printf("
    ");
    14 }

    (3)插入节点
    编写函数:void insert_ linklist(link_node* head,int val,int data).
    在指定值后面插入数据 data,如果值val不存在,则在尾部插入。

     1 //在值val前插入节点
     2 void insert_linklist(link node* head,int val,int data){
     3 
     4     if(head==NULL){
     5         return;
     6     }
     7 
     8     //两个辅助指针
     9     link node* p prev=head;
    10     1ink node* p_current=p_prev->next;
    11     while(p_current!=NULL){
    12         if(pcurrent->data==val){
    13             break;
    14         }
    15         p_prev=p_current;
    16         p_current=pprev->next;
    17     }
    18     //如果p_current为NULL,说明不存在值为val的节点
    19     if(p_current==NULL){
    20         printf("不存在值为%d的节点!
    ",val);
    21         return;
    22     }
    23 
    24     //创建新的节点
    25     1ink_node* newnode=(1ink_node*)malloc(sizeof(1ink_node));
    26     newnode->data=data;
    27     newnode->next=NULL;
    28 
    29     //新节点入链表
    30     newnode->next=p_current;
    31     p_prev->next=newnode;
    32 }

    (4)删除节点
    编写函数:void remove _linklist(link node* head,int val)
    删除第一个值为val的结点.

     1 //删除值为val的节点
     2 void remove_linklist(1ink node* head,int val){
     3     if(head==NULL){
     4         return;
     5     }
     6     
     7     //辅助指针
     8     1ink_node* pprev=head;
     9     1ink_node*p_current=p prev->next;
    10 
    11     //查找值为val的节点
    12     while(pcurrent!=NULL){
    13         if(p_current->data==val){
    14             break;
    15         }
    16         p_prev=p_current;
    17         p_current=p prev->next;
    18     }
    19     //如果p_current为NULL,表示没有找到
    20     if(p_current==NULL){
    21         return;
    22     }
    23     
    24     //删除当前节点:重新建立待删除节点(p_current)的前驱后继节点关系
    25     p_prev->next=p_current->next;
    26     //释放待删除节点的内存
    27     free(p_current);
    28 }

    (5)销毁链表
    编写函数:void destroy_linklist(link_node* head)
    销毁链表,释放所有节点的空间.

     1 //销毁链表
     2 void destroy_linklist(link node* head){
     3     if(head==NULL){
     4         return;
     5     }
     6     //赋值指针
     7     1ink node* pcurrent=head;
     8     while(p_current!=NULL){
     9         //缓存当前节点下一个节点
    10         1ink_node* pnext=p_current->next;
    11         free(p_current);
    12         p_current=p_next;
    13     }
    14 }

     
    练习:链表的操作


    LinkList.h

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #pragma once
     3 
     4 #include<stdlib.h>
     5 #include<stdbool.h>
     6 #include<stdio.h>
     7 
     8 #ifdef __cplusplus
     9 extern "C"{
    10 #endif
    11 
    12     //定义节点数据类型
    13     struct LinkNode
    14     {
    15         int data;
    16         struct LinkNode* next;
    17     };
    18     
    19     //初始化链表
    20     struct LinkNode* Init_LinkList();
    21     //在值为oldval的位置插入一个新的数据newval
    22     void InsertByValue_LinkList(struct LinkNode* header, int oldval, int newval);
    23     //删除值为val的结点
    24     void RemoveByValue_LinkList(struct LinkNode* header, int delValue);
    25     //遍历
    26     void Foreach_LinkList(struct LinkNode* header);
    27     //销毁链表
    28     void Destroy_LinkList(struct LinkNode* header);
    29     //清空
    30     void Clear_LinkList(struct LinkNode* header);
    31     
    32 
    33 #ifdef __cplusplus
    34 }
    35 #endif

    LinkList.c

      1 #include"LinkList.h"
      2 
      3 
      4 //初始化链表
      5 struct LinkNode* Init_LinkList()
      6 {
      7     //创建头结点
      8     struct LinkNode* header = malloc(sizeof(struct LinkNode));
      9     header->data = 1;
     10     header->next = NULL;
     11     
     12     //尾部指针
     13     struct LinkNode* pRear = header;
     14     
     15     int val = 1;
     16     while(true)
     17     {
     18         printf("输入插入的数据:
    ");
     19         scanf("%d", &val);
     20         if(val == -1)
     21         {
     22             break;
     23         }
     24         
     25         //先创建新结点
     26         struct LinkNode* newnode = malloc(sizeof(struct LinkNode));
     27         newnode->data = val;
     28         newnode->next = NULL;
     29         
     30         //新结点插入到链表中
     31         pRear->next = newnode;
     32         
     33         //更新尾部指针指向
     34         pRear = newnode;
     35     }
     36     return header;
     37 }
     38 //在值为oldval的位置插入一个新的数据newval
     39 void InsertByValue_LinkList(struct LinkNode* header, int oldval, int newval)
     40 {
     41     if(NULL == header)
     42     {
     43         return;
     44     }
     45     //两个辅助指针变量
     46     struct LinkNode* pPrev = header;
     47     struct LinkNode* pCurrent = pPrev->next;
     48     while(pCurrent != NULL)
     49     {
     50         if(pCurrent->data == oldval)
     51         {
     52             break;
     53         }
     54         
     55         pPrev = pCurrent;
     56         pCurrent = pCurrent->next;
     57     }
     58 #if 0//也可以更改为插入到链表的尾部
     59     //如果pCurrent为NULL,说明链表中不存在值为oldval的结点
     60     if(pCurrent == NULL)
     61     {
     62         return;
     63     }
     64 #endif    
     65     //先创建新结点
     66     struct LinkNode* newnode = malloc(sizeof(struct LinkNode));
     67     newnode->data = newval;
     68     newnode->next = NULL;
     69     
     70     //新结点插入到链表中
     71     newnode->next = pCurrent;
     72     pPrev->next = newnode;
     73     
     74 }
     75 //删除值为val的结点
     76 void RemoveByValue_LinkList(struct LinkNode* header, int delValue)
     77 {
     78     if(NULL == header)
     79     {
     80         return;
     81     }
     82     //两个辅助指针变量
     83     struct LinkNode* pPrev = header;
     84     struct LinkNode* pCurrent = pPrev->next;
     85     
     86     while(pCurrent != NULL)
     87     {
     88         if(pCurrent->data == delValue)
     89         {
     90             break;
     91         }
     92         
     93         //移动两个辅助指针
     94         pPrev = pCurrent;
     95         pCurrent = pCurrent->next;
     96     }
     97     
     98     if(NULL == pCurrent)
     99     {
    100         return;
    101     }
    102     
    103     //重新建立待删除结点的前驱和后继结点的关系
    104     pPrev->next = pCurrent->next;
    105     //释放删除结点内存
    106     free(pCurrent);
    107     pCurrent = NULL;
    108 }
    109 //遍历
    110 void Foreach_LinkList(struct LinkNode* header)
    111 {
    112     if(NULL == header)
    113     {
    114         return;
    115     }
    116     //辅助指针变量
    117     struct LinkNode* pCurrent = header->next;
    118     
    119     while(pCurrent != NULL)
    120     {
    121         printf("%d ", pCurrent->data);
    122         pCurrent = pCurrent->next;
    123     }
    124     
    125 }
    126 //销毁链表
    127 void Destroy_LinkList(struct LinkNode* header)
    128 {
    129     if(NULL == header)
    130     {
    131         return;
    132     }
    133     //辅助指针变量
    134     struct LinkNode* pCurrent = header;
    135     while(pCurrent != NULL)
    136     {
    137         //先保存下当前结点的下一个结点地址
    138         struct LinkNode* pNext = pCurrent->next;
    139         
    140         //释放当前结点内存
    141         free(pCurrent);
    142         
    143         //指针向后移动
    144         pCurrent = pNext;
    145     }
    146     
    147 }
    148 //清空
    149 void Clear_LinkList(struct LinkNode* header)
    150 {
    151     if(NULL == header)
    152     {
    153         return;
    154     }
    155     
    156     //辅助指针变量
    157     struct  LinkNode* pCurrent = header->next;
    158     
    159     while(pCurrent != NULL)
    160     {
    161         //先保存下当前结点的下一个结点地址
    162         struct LinkNode* pNext = pCurrent->next;
    163         
    164         //释放当前结点内存
    165         printf("%d结点被销毁
    ",pCurrent->data);
    166         free(pCurrent);
    167         
    168         //pCurrent指向下一个结点
    169         pCurrent = pNext;
    170     }
    171     header->next = NULL;
    172 }

    链表操作练习.c

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 #include"LinkList.h"
     6 
     7 
     8 void test()
     9 {
    10     //初始化链表100 200 300 400 500 600
    11     struct LinkNode* header = Init_LinkList();
    12     //打印链表
    13     Foreach_LinkList(header);
    14     //插入数据
    15     InsertByValue_LinkList(header, 300, 666);
    16     //打印链表
    17     printf("--------------
    ");
    18     Foreach_LinkList(header);
    19     
    20     //清空链表
    21     Clear_LinkList(header);
    22     //打印链表
    23     printf("
    --------------
    ");
    24     Foreach_LinkList(header);
    25     
    26     InsertByValue_LinkList(header, 1000, 111);
    27     InsertByValue_LinkList(header, 1000, 211);
    28     InsertByValue_LinkList(header, 1000, 311);
    29     InsertByValue_LinkList(header, 1000, 411);
    30     //打印链表
    31     printf("
    --------------
    ");
    32     Foreach_LinkList(header);
    33     
    34     RemoveByValue_LinkList(header, 311);
    35     //打印链表
    36     printf("
    --------------
    ");
    37     Foreach_LinkList(header);
    38     
    39     RemoveByValue_LinkList(header, 211);
    40     //打印链表
    41     printf("
    --------------
    ");
    42     Foreach_LinkList(header);
    43     
    44     //销毁链表
    45     Destroy_LinkList(header);
    46 }
    47 
    48 int main(){
    49 
    50     test();
    51     
    52     system("pause");
    53     return EXIT_SUCCESS;
    54 }

    参考:

    1)讲义:豆丁网:https://www.docin.com/p-2159552288.html
    道客巴巴:https://www.doc88.com/p-6951788232280.html

    在学习c语言提高总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    jquery之滚楼
    jquery之仿京东菜单
    jquery之鼠标移动[沸腾京东]
    jquery之飘雪
    jquery之手风琴
    jquery 开始与结束方法 loading窗
    JS对象与数组
    Selenium+Python浏览器调用:Firefox
    Python脚本检查网页是否可以打开
    ubuntu安装pycharm教程
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/C_ImprovedLearning_06.html
Copyright © 2020-2023  润新知