• C语言链表理论(高阶篇三十六)


      动态内存分配

        程序1

          sizeof与结构

    //36-1 sizeof与结构.c
    
    #include <stdio.h>
    #pragma    pack(1)    //字节对齐
    
    struct student     //定义结构类型
    { 
        char name[9];
        char sex[3];
        int age;
    }*pstu, stu = {"王什","",46};
    
    main()
    {
        double d, *pd = &d;    //双精度浮点型
        printf("%d\n", sizeof(struct student));  //结构内存
        printf("%d\n", sizeof(stu));     //结构变量内存
        printf("%d\n", sizeof(pstu));     //结构指针内存
    
        printf("%d\n", sizeof(double));     //双精度浮点型内存
        printf("%d\n", sizeof(d));     //双精度浮点型变量内存
        printf("%d\n", sizeof(pd));     //双精度浮点型变量内存
    
    }

        ※在sizeof中使用变量和类型效果一样,如果计算的是变量,它只会计算出变量对应类型所占的字节数。

        普通的变量定义,在定义时分配内存,函数结束时释放内存,这一切都由系统自动完成。在C语言中,程序员也可以自由地,不受系统控制地手动分配内存。若要手动分配内存,需要用到以下知识点:

          ※使用sizeof函数计算变量或类型的大小

          ※使用malloc函数、free函数分配内存

          ※使用指针指向已分配的内存。

        程序2

          无名变量

    // 36-2无名变量.c
    
    #include <stdio.h>
    
    main()
    {
        int *p1, *p2, *p3;   //定义三个整型指针
        p1 = (int*)malloc(sizeof(int));   //p1指针分配4字节内存空间
        p2 = (int*)malloc(sizeof(int));   //p2指针分配4字节内存空间
        p3 = (int*)malloc(sizeof(int));   //p3指针分配4字节内存空间
        printf("变量地址:%d,%d,%d\n", p1, p2, p3);  //分配的地址
        *p1 = 10;
        *p2 = 20;
        *p3 = 30;
        printf("变量内容:%d,%d,%d\n", *p1, *p2, *p3);  //内容
    
        free(p1);    //释放内存
        free(p2);
        free(p3);
        printf("变量内容:%d,%d,%d\n", *p1, *p2, *p3);  //释放后的内容
    }

        ※malloc和free通常配对使用,malloc的内存如果没有用free释放,会造成“内存泄露”。

      链表原理

        使用数组存储数据时,所有的数据在内存中连成一片,需要取出某个数据,只要报上它在内存中的房间编号(数组下标)即可马上取出。

        数组也有缺点,它必须预先分配好一些内存,如果这些内存未全部使用,其它的就浪废了。这在字符串的使用中尤为明显:

          char str[100]=”hello!”;

        程序员定义这个字符串最大能接受99个字符。但是在这里因为实际需求只用了前面7个字符,后面的93个字节就浪废了,浪废率达到90%。

        于是软件工程师们就想出“链表”这种存储方法,它的内存结构如下:

          

        在C语言中,一般用结构表示链表:

          struct student

          {

            char name[9]; /*姓名*/

            int age; /*年龄*/

            struct student *pNext; /*下一结点*/

          };

        ※老师带小朋友游玩时,老师用手拉着第一个小朋友,第一个小朋友又拉着后面的小朋友,以此类推……

        这里的“头指针”可以比作老师的手,后面的“指针”就像小朋友的手,最后一个小朋友后面没有拉人,所以它设置为NULL。

        链表这种结构,就像锁链一样,一环扣着一环,有一个环坏了,后面所有的结点都会丢失,这就是链表的特点。

        程序3

          手拉手的小朋友

    // 36-3手拉手小盆友(链表简单使用).c
    
    #include <stdio.h>
    
    struct  kid      //小盆友结构变量
    {
        char name[9];
        int age;
        struct kid *pHand;    //指针指向下一个小盆友
    };
    
    main()
    {
        struct kid k1 = { "小名",3 };
        struct kid k2 = { "小红",4 };
        struct kid k3 = { "小冰",6 };
        k1.pHand = &k2;   //第一个小朋友拉着第二个小盆友的手
        k2.pHand = &k3;      //第二个小朋友拉着第三个小盆友的手
        k3.pHand = NULL;
        printf("%s拉着的小盆友是:%s\n", k1.name, k1.pHand->name);  //换种写法: (*k1.pHand).name
        printf("%s拉着的小盆友是:%s\n", k2.name, k2.pHand->name);
    }

      名词解释

        结点(Node):

          在《数据结构》中,结点通常表示一个数据单位,比如在数组中,数组元素可称为结点。在“树”结构中,每个分支元素也称为结点。如:设系为根结点,班是系的子结点,学生是班的子结点。反推过去,系是班的父结点,班是学生的父结点,系是所有子结点的祖宗结点。

          链表和数组都不是用来描述父子关系的,它们通常用来描述“兄弟关系”,所以结点与结点的关系不像“树”结构这么复杂。

      作业

    // 36-4练习.c
    
    #include <stdio.h>
    fut(int **s, int p[2][3])
    {
        **s = p[1][1];   //指针与二维数组中   **s = *(*(s+0)+0)  取内容
    }
    main()
    {
        int a[2][3] = { 1,3,5,7,9,11 }, *p;
        p = (int*)malloc(sizeof(int));     //定义一个无名变量
        fut(&p, a);   
        printf("%d\n", *p);    //结果是 : 9
    }

     

  • 相关阅读:
    python笔记005-字符串-列表-元组
    Python笔记2 标准数据类型
    VS2010与VAssistX
    【Windows核心编程】Windows常见数据类型
    网络安全加密
    防御 XSS 的七条原则
    用户权限初略设计
    [Android]Handler的消息机制
    java的线程中的Runnable
    [转]永久告别Android的背景选择器Selector!无需切很多图了!
  • 原文地址:https://www.cnblogs.com/httpcc/p/15552450.html
Copyright © 2020-2023  润新知