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;
        }
    }

  • 相关阅读:
    6)图[5]最短路径
    6)图[4]关键路径
    6)图[3]拓扑排序算法
    6)图[2]Prim算法[最小生成树]
    Aprori算法[关联规则算法]
    K-Modes算法[聚类算法]
    linux Centos6.7 python交互模式下回退异常问题解决
    Python-面向对象(二)-Day7
    Python-面向对象(一)-Day7
    (error) MISCONF Redis is configured to save RDB snapshots
  • 原文地址:https://www.cnblogs.com/qinkai/p/2429592.html
Copyright © 2011-2022 走看看