zoukankan      html  css  js  c++  java
  • 动态内存分配

    动态内存分配及练习
    malloc与free使用时的注意事项:
    1)配对使用,有一个malloc,就应该有一个
    free
    2)尽量在同一层上使用,不要出现malloc在函
    数中,而free在函数外。最好在同一调用层上
    使用这两个函数
    3)malloc分配的内存一定要初始化
    free后的指针不允许再使用

    链表的基本操作

    链表的构成:
    链表通过在每个结构体变量中设置指向下一个变量的指针域,并存入下一个变量的地址,
    实现将一组结构体变量链成一条链表
    链表中的每个结构体变量称为该链表的一个节点,每个节点的单元一般都没有名字,它们是
    通过动态分配函数生成的

    链表作为一个线性存储结构,链表的使用比数组灵活的多,因为构造一个链表时不一定在程序中
    指定链表的长度(节点的个数),可以在程序的运行过程中动态动态的生成一个链表而且链表使
    用完后还可以通过函数free释放掉整个链表空间。

    链表的每个结点都分为两个域,一个是数据域,存放各种实际的数据,另一个域为指针域,
    存放下一结点的首地址
    链表中的每一个结点都是同一种结构类型

    链表的基本操作对链表的主要操作有以下几种:
    1.建立链表;
    2.遍历输出;
    3.结构的查找与输出;
    4.插入一个结点;
    5.删除一个结点;
    6.链表排序

    建立动态链表
    指在程序执行过程中从无到有地建立起一个链表,即一个一个地
    开辟结点和输入各结点数据,并建立起前后相链的关系

    一般有两种形式
    正挂—即先建立链头,让链头指向首先开辟并输入数据的第一个结点;然后开辟并输入第二个结点
          数据,将其“挂”到第一个结点之后..即按输入顺序将结点“挂”接在一起
    倒挂—最先输入的结点作尾结点,后输入的结点始终“挂”在链头上,即按由后向前的顺序建立链表

    链表的插入分为四种情况:
    ① 原表是空表:只需使head指向被插结点即可
    ② 在第一个结点之前插入:使head指向被插结点,被插
    结点的指针域指向原来的第一结点即可
    ③ 在其它位置插入:使插入位置的前一结点的指针域指
    向被插结点,使被插结点的指针域指向插入位置的后
    一结点
    ④ 在表末插入,使原表末结点指针域指向被插结点,被
    插结点指针域置为NULL

    链表删除:     
         删除是将某一结点从链中摘除,即将待删结点与其前一结点解除联系。
    删除一个节点有两种情况:
     1、被删除结点是第一个结点:只需使head指向第二个结点即可,即head=head->next
     2、被删结点不是第一个结点:使被删结点的前一结点指向被删结点的后一结点即可,
                               即pf->next=pb->next

    信息管理系统练习    

    《学生信息管理系统1》
    1. 遍历输出
    2. 链表查找
    3. 链表插入
    4. 链表删除

    1. 设计保存学生信息的链表
    4. 可随时添加学生信息,将新加入的学生信
       息按学号顺序添加到链表中
    2. 设计遍历输出函数
    3. 设计查找函数,根据学号查找或姓名查找
    5. 可随时删除学生信息,根据学号删除

    习题答案
    main.c:
    #include "link.h"

    void display(void)
    {
        system("cls");
        printf("\r************************\n");
        printf("***** 1、创建链表  *****\n");
        printf("***** 2、增加节点  *****\n");
        printf("***** 3、删除节点  *****\n");
        printf("***** 4、查找链表  *****\n");
        printf("***** 5、链表排序  *****\n");
        printf("***** 6、输出链表  *****\n");
        printf("***** 7、回收链表  *****\n");
        printf("***** 0、退出程序  *****\n");
        printf("************************\n");
        printf("你要我做什么? 请选择^_^\n");

    }
    void fun(void)
    {
        stulink *student,*temp;
        uint n = 0;
        char ch = 0;
        char flag  = 0;
        display();
        while(1)
        {    
            ch=getch();
            switch(ch)
            {
                case '1'://创建链表
                    display();
                    printf("\n请输入链表的长度: ");
                    scanf("%d", &n);
                    student = creatlink(n);
                    printlink_all(student);
                    printf("你要我做什么? 请选择^_^\n");
                    break;
                case '2'://增加节点
                    display();
                    printf("增加节点前的链表:\n\n");
                    printlink_all(student);
                    addtlink(student);
                    printf("增加节点后的链表:\n\n");
                    printlink_all(student);
                    printf("你要我做什么? 请选择^_^\n");
                    break;
                case '3'://删除节点
                    display();
                    printf("删除节点前的链表:\n\n");
                    printlink_all(student);
                    printf("\n请要删除的学号: ");
                    scanf("%d", &n);
                    delettlink_element(&student,n);
                    printf("删除节点后的链表:\n\n");
                    printlink_all(student);
                    printf("你要我做什么? 请选择^_^\n");
                    break;
                case '4'://查找链表
                    display();
                    printlink_all(student);
                    printf("请输入要查找的学号: ");
                    scanf("%d", &n);
                    temp = searchlink(student,n);
                    if(temp)
                    {
                        printf("\n为你找到的结果:\n");
                        printlink_element(temp);
                    }
                    else
                    {
                        printf("未找到此学号的学生信息!\n");
                    }
                    printf("你要我做什么? 请选择^_^\n");
                    break;
                case '5'://链表排序
                    display();
                    printf("排序前节点前的链表:\n\n");
                    printlink_all(student);
                    inorderlink(&student);
                    printf("排序后节点后的链表:\n\n");
                    printlink_all(student);
                    printf("你要我做什么? 请选择^_^\n");
                    break;
                case '6'://输出链表
                    display();
                    printf("排序后的链表:\n\n");
                    printlink_all(student);
                    printf("你要我做什么? 请选择^_^\n");
                    break;
                case '7'://回收链表
                    display();
                    freelink(student);
                    printf("你要我做什么? 请选择^_^\n");
                    break;
                case '0'://退出程序
                    flag = 1;
                    break;
                default:
                    display();
                    printf("\n按键非法,请重新输入!^_^\n");
                    break;
            }
            if(flag)
            {
                break;
            }
        }
    }

    int main(void)
    {
        fun();
        return 0;
    }

    link.h:
    #ifndef __link_h__
    #define __link_h__

    #include <stdlib.h>
    #include <stdio.h >
    #include <conio.h>
    typedef unsigned char uchar;
    typedef unsigned int uint;

    typedef struct student
    {
        uint id;
        uchar name[16];
        uchar age;
        struct student *next;
    } stulink;


    /*******************************************************

    *功能:     创建一个具有n个节点的链表,并对其值进行初始化
    *方式:     正挂
    *参数:        n: 链表的长度,即节点的个数
    *返回值:    所创建链表的首地址

    ********************************************************/
    extern stulink *creatlink(uint n);

    /*******************************************************

    *功能:     遍历输出链表
    *参数:        链表的表头
    *返回值:    无

    ********************************************************/
    extern void printlink_all(stulink *head);

    /*******************************************************

    *功能:     链表查找
    *参数:        链表的表头,要查找的学号
    *返回值:    要输出链表的元素的首地址

    ********************************************************/
    extern stulink *searchlink(stulink *head, uint id);

    /*******************************************************

    *功能:     链表输出
    *参数:        要输出链表的元素的首地址
    *返回值:    无

    ********************************************************/
    extern void printlink_element(stulink *element);

    /*******************************************************

    *功能:     增加一个链表元素至链表结尾
    *参数:        链表的元素的首地址
    *返回值:    无

    ********************************************************/
    extern void addtlink(stulink *head);

    /*******************************************************

    *功能:     删除一个链表元素
    *参数:        链表的元素的首地址,学生的学号
    *返回值:    无

    ********************************************************/
    extern void delettlink_element(stulink **head, uint id);

    /*******************************************************

    *功能:     链表的元素按学号大小从小到大排序
    *参数:        链表的元素的首地址
    *返回值:    无

    ********************************************************/
    void inorderlink(stulink **head);

    /*******************************************************

    *功能:     回收链表
    *参数:        链表的元素的首地址
    *返回值:    无

    ********************************************************/
    void freelink(stulink *head);


    #endif

    link.c:
    #include "link.h"

    /*******************************************************

    *功能:     创建一个具有n个节点的链表,并对其值进行初始化
    *方式:     正挂
    *参数:        n: 链表的长度,即节点的个数
    *返回值:    所创建链表的首地址

    ********************************************************/
    stulink *creatlink(uint n)
    {
        stulink *head,*temp,*previous;
        uint i;
        for(i=0;i<n;i++)
        {
             temp = (stulink *)malloc(sizeof(stulink));
            if(temp == NULL)
            {
                 printf("内存分配失败,创建链表失败\n");
                head = NULL;
                break;
            }
            printf("请输入学号 姓名 年龄(中间用空格格开):");
             scanf("%d %s %d", &(temp->id), &(temp->name), &(temp->age));
            if(i==0)
            {
                previous = head = temp;
            }
            else
            {
                previous->next = temp;
                previous = temp;
            }
            previous->next = NULL;
        }
        if(n == 0)
        {
            head = NULL;
        }
        return head;
    }

    /*******************************************************

    *功能:     遍历输出链表
    *参数:        链表的表头
    *返回值:    无

    ********************************************************/
    void printlink_all(stulink *head)
    {
        stulink *nextpr;
        nextpr = head;
        while(nextpr)
        {
            printf("学号:%d 姓名:%s 年龄:%d\n", nextpr->id, nextpr->name, nextpr->age);
            nextpr = nextpr->next;
        }
    }

    /*******************************************************

    *功能:     链表查找
    *参数:        链表的表头,要查找的学号
    *返回值:    要输出链表的元素的首地址

    ********************************************************/
    stulink *searchlink(stulink *head, uint id)
    {
        stulink *nextpr;
        nextpr = head;
        while(nextpr!=NULL)
        {
            if(nextpr->id == id)
            {
                return nextpr;
            }
            else
            {
                nextpr = nextpr->next;
            }        
        }
        return NULL;
    }

    /*******************************************************

    *功能:     链表输出
    *参数:        要输出链表的元素的首地址
    *返回值:    无

    ********************************************************/
    void printlink_element(stulink *element)
    {
        printf("学号:%d 姓名:%s 年龄:%d\n", element->id, element->name, element->age);
    }

    /*******************************************************

    *功能:     增加一个链表元素至链表结尾
    *参数:        链表的元素的首地址
    *返回值:    无

    ********************************************************/
    void addtlink(stulink *head)
    {
        stulink *nextpr,*temp;
        nextpr = head;
        while(nextpr)
        {
            temp = nextpr;
            nextpr = nextpr->next;
        }
        nextpr = (stulink *)malloc(sizeof(stulink));
        if(nextpr == NULL)
        {
            printf("内存分配失败,增加链表元素失败\n");
        }
        else
        {
            printf("请输入学号 姓名 年龄(中间用空格格开):");
            scanf("%d %s %d", &(nextpr->id), nextpr->name, &(nextpr->age));
            nextpr->next = NULL;
            temp->next = nextpr;
        }
    }

    /*******************************************************

    *功能:     删除一个链表元素
    *参数:        链表的元素的首地址,学生的学号
    *返回值:    无

    ********************************************************/
    void delettlink_element(stulink **head, uint id)
    {
        stulink *nextpr;
        uint i = 0, j = 0;        //i:链表元素个数
        stulink **arry;

        nextpr = *head;
        while(nextpr)
        {    
            i++;
            if(nextpr->id==id)
            {
                j = i;
            }
            nextpr = nextpr->next;    
        }
        if(j==0)
        {
            printf("未找到相应学号学生信息!\n");
        }
        else
        {
            arry = calloc(i,sizeof(arry));
            nextpr = *head;
            i = 0;
            while(nextpr)
            {    
                *(arry+i) = nextpr;//保存链表各元素地址
                i++;
                nextpr = nextpr->next;    
            }
            if(i==0)
            {
                printf("这是一个空链表,不能删除元素!\n");
            }
            else
            {
                if(i==1)
                {
                    printf("删除元素后,这是一个空链表!\n");
                    free(arry[0]);
                     *head = NULL;
                }
                else if(i>1 && j==1)
                {
                    free(arry[0]);
                    *head = arry[1];        
                }
                else if(i>1 && j>1 && j<=i)
                {
                    arry[j-2]->next = arry[j-1]->next;
                    free(arry[j-1]);
                }
            }
            free(arry);
        }
    }

    /*******************************************************

    *功能:     链表的元素按学号大小从小到大排序
    *参数:        链表的元素的首地址
    *返回值:    无

    ********************************************************/
    void inorderlink(stulink **head)
    {
        stulink *nextpr,*temp;
        uint i = 0,j,k;        //i:链表元素个数
        stulink **arry;

        nextpr = *head;
        while(nextpr)
        {    
            i++;
            nextpr = nextpr->next;    
        }
        arry = calloc(i,sizeof(arry));
        nextpr = *head;
        for(j=0;j<i;j++)
        {    
            *(arry+j) = nextpr;//保存链表各元素地址
            nextpr = nextpr->next;    
        }
        for(j=0;j<i-1;j++)//按照各链表元素的id从小到大排序,将各元素放入指针数组中
        {
            for(k=j+1;k<i;k++)
            {
                if((*(arry+j))->id > (*(arry+k))->id)
                {
                    temp = *(arry+k);
                    *(arry+k) = *(arry+j);
                    *(arry+j)= temp;
                }
            }
        }
        *head = *arry;
        for(j=0;j<i-1;j++)    //按照指针数组中的各链表元素的地址的顺序重新给链表安排指针域
        {
            (*(arry+j))->next = *(arry+j+1);
        }
        (*(arry+i-1))->next = NULL;
        free(arry);
    }

    /*******************************************************

    *功能:     回收链表
    *参数:        链表的元素的首地址
    *返回值:    无

    ********************************************************/
    void freelink(stulink *head)
    {
        stulink *temp;
        while(head)
        {
            temp=head->next;
            free(head);
            head=temp;
        }
    }

  • 相关阅读:
    Notes about "Exploring Expect"
    Reuse Sonar Checkstyle Violation Report for Custom Data Analysis
    Eclipse带参数调试的方法
    MIT Scheme Development on Ubuntu
    Manage Historical Snapshots in Sonarqube
    U盘自动弹出脚本
    hg的常用配置
    Java程序员的推荐阅读书籍
    使用shared memory 计算矩阵乘法 (其实并没有加速多少)
    CUDA 笔记
  • 原文地址:https://www.cnblogs.com/qinkai/p/2429592.html
Copyright © 2011-2022 走看看