8.7用结构体实现链表

如果要存储多个学生的数据,但又不知道有多少个学生,怎么存储呢?可以定义一个很大的结构体数组,但浪费存储空间。一种较好的方法是结合指针和结构体来实现:对输入的每一个同学的数据,动态申请一个结构体变量存储他的数据;并“设法”将存储这些学生数据的结构体变量“串接”起来,如下图所示。这样的好处是既节省存储空间;又能访问每个学生的数据因为它们已经“串接”成一个整体了

怎样将相同类型的结构体变量“串接”起来呢?我们知道指针的作用是用来指向某个变量。如果在结构体中包含一个基类型为同种结构体类型的指针成员,那就可以实现“串接”。例如,我们可以在前面引入的student结构体中增加一个指针成员。此处的next指针需要指向下一个学生的数据,所以基类型必须是student类型

struct student
{
    char name[20];
    int age;
    double score;
    student *next;   //改成“int *p;”更利于理解
};

在C语言中,动态申请存储空间要用malloc函数实现,释放存储空间要用free函数实现。在C++语言中,动态申请存储空间和释放存储空间分别是用new和delete运算符实现的。以下只介绍new、delete运算符
(1)申请单个变量所占存储空间的形式为:
指针变量名 = new 类型名(初值);    //初值是可选的
例如:
int *p1, *p2, *p3;
p1 = new int;    //申请一个存放整数的存储空间(没有名称),返回给指针p1
p2 = new int(100);    //申请一个存放整数的空间,初值为100 

(2)申请数组存储空间的形式为:
指针变量名 = new 类型名[表达式];
其中表达式为数组长度,可以包含变量。例如:
int n = 5;
p3 = new int[n];    //申请一个存放5个元素的空间,将存储空间首地址赋给p3

(3)释放单个变量所占存储空间的形式为:
delete 指针变量名; 

(4)释放数组存储空间的形式为:
delete [ ]指针变量名;
例如:
delete p1;     //释放由p1所指向的单个变量所占的存储空间
delete [ ]p3;    //释放由p3所指向的数组存储空间
注意,如果释放数组存储空间时,忘了写[ ],那么只能释放第0个元素所占存储空间,其他元素所占存储空间未能释放
释放存储空间后,又可以重新申请新的存储空间。例如:
n = 10;
p3 = new int[n];    //申请一个存放10个元素的空间,将存储空间首地址赋给p3
在student结构体中增加next指针成员后,就可以实现简单链表了  

例1:输入每个学生的数据(包括姓名、年龄、分数),当输入“END”时代表输入结束。对输入的每个学生的数据,动态申请存储空间来存储,并将每个学生的数据构造链表。输出每个学生的姓名。最后释放链表中的结点

#include<bits/stdc++.h>
using namespace student
struct student
{
    char name[20];
    int age;
    float score;
    student *next;   //指向下一个结构体变量的指针成员
};(
int main()
{
    char name1[30];
    student *head = NULL;  //指向第一个结点的指针
    student *p = NULL;   //用来动态申请存储空间
    int first = 1;  //是否是第一个学生的标志
    while(1){   //用针循环
        cin getline(name1, 20);  //输入学生姓名,允许有空格
        if(strcmp(name1,"END")==0) break;   //输入END代表输入结束
        pt = new student;   //动态申请可以储存一个student数据的存储空间
        strcpy(py->name, name1);
        cin >> pt -> age;  //输入年龄
        cin >> pt -> score;  //输入成绩
        pt->next = NULL;
        //以下构造链表
        if(first){  //第一个结点
            first = 0; head = p = pt;
        }
        else{  //在链表末尾插入结点
            p->next = pt; p = p->next;
        }
        getchar();   //跳过末尾的回车键,否则下一次getline()函数读入该回车键
    }
    pt = head;
    while(pt){  //等价于pt!=NULL
        cout << pt -> name << endl;  //输出所有学生的姓名
        pt = pt -> next;  //pt指向下一个学生
    }
    p = head; head = NULL;
    while(p){  //等价于p!=NULL
        pt = p;
        p = p->next;
        delete pt;  //释放所有结点所占存储空间
    }
    return 0;
}

该程序包含两个重要的过程:
构造链表、释放链表
三个指针的作用:
①head指针:指向头结点(即第个结点);
②p指针:指向当前结点(即当前最后一个结点);
③pt指针:指向新申请的结点

if(first){  //第一个结点
	first 0; head = p = pt;
else{   //在链表末尾插入结点
p->next pt; p = p->next;
}

释放链表过程中两个指针的作用为:
①p指针:指向剩余链表中的第一个结点
②pt指针:指向将被释放的结点

    p = head; head = NULL;
    while(p){  //等价于p!=NULL
        pt = p;
        p = p->next;
        delete pt;  //释放所有结点所占存储空间
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值