数组是由相同类型的数据元素组成,而结构是由一组不同的数据类型构成。结构类型为 处理复杂的数据提供了便利的手段。如一个学生的信息就是由姓名、性别、出生日期、籍贯、
成绩等不同类型的数据共同组成,它如同数据库表的结构。结构与数组都是构造类型,也十分 相似,都是由若干分量组成,结构中的分量称为结构成员。
4.6.1 结构
在程序中使用结构之前,首先要对结构的组成进行描述,称为结构类型的定义。
1.结构类型定义 形式:
struct 结构类型标识符 {
结构成员 1;
结构成员 2;
结构成员 n;
};
说明:
(1)说明结构类型的关键字是 struct,其后的结构类型标识符是所定义的结构类型名。
(2)结构类型是一种混合的数据类型,其成员可为任意类型,只有自身的实例除外。
例如,描述一个人的出生日期可以说明下面的结构类型:
struct date {
int month;
int day;
int year;
};
该结构类型的变量又可以作为其他结构类型的成员。例如:
struct man {
char name[15];
char sex;
int age;
struct date birthday;
};
以上说明了一个结构类型 struct man,其中有一个成员 birthday 又是 struct date 类型的变量,
其结构如图 4.22 所示。
birthday
name sex age
month day year
图 4.22 结构类型 struct man 2.结构类型变量的定义
从语法上来说,用户自定义的结构类型的地位等同于 char、int、float、double 等标准类型。
结构类型本身并不占用存储空间,只有结构变量才需要分配存储空间。结构变量的成员在内存 中占用一片连续存储区域,其大小为结构中每个成员的长度之和。C++语言中提供了 3 种利用 已说明的结构类型定义结构变量的方法。
(1)说明结构类型的同时定义结构变量,如:
struct man {
char name[15];
char sex;
int age;
struct date birthday;
}m1;
以上在说明结构类型 man 的同时定义了一个该类型的变量 m1。
(2)省略类型名,直接定义结构变量,如:
struct {
char name[15];
char sex;
int age;
struct date birthday;
}m[3];
此处定义了一个包含 3 个元素的结构数组,其中每个元素都是一个包含若干个成员的结 构类型数据。C++语言中允许定义这种无类型名的变量。
(3)说明结构类型之后,再定义该类型的变量,如:
struct man m2,*p;
该语句定义了一个 struct man 类型的变量 m2 和指向结构类型的指针变量 p。
3.结构类型变量的引用
(1)普通结构变量成员的访问。
形式:结构变量名.成员名
其中,“.”是成员访问运算符,是优先级最高的运算符之一。如果结构变量的成员本身也 是结构类型,则需要使用多个“.”运算符来实现。
例如,对前面定义过的 m1 变量进行赋值:
strcpy (m1.name, "Wang Min");
m1.sex = 'F';
m1.age = 24;
m1.birthday.month = 8;
m1.birthday.day = 10;
m1.birthday.year = 1985;
(2)通过指针访问结构变量的成员。
形式:(*指向结构的指针).成员名 或
指向结构的指针->成员名
注意:不能省略圆括号。运算符“->”与“.”运算符相同,具有所有运算符中最高的优 先级。假设有定义:
struct man1 m,*p=&m;
则可以这样对结构变量 m 的成员赋值:strcpy(p->name, "Wang Min");。
【例 4.16】用结构数组保存学生数据并显示。
程序如下:
//Ex4_16.cpp
#include "iostream"
#include "cstring"
using namespace std;
struct person {
char name[10]; //姓名 bool sex; //性别 int age; //年龄 float score; //成绩 }a[10];
void main() {
int n,i,k;
person x;
cout<<"请输入一个正整数(1~n):";
cin>>n;
cout<<"从键盘输入具有 person 结构的"<<n<<"个记录:"<<endl;
for(i=0;i<n;i++) {
cin>>x.name;
cin>>k;
if (k==1) x.sex=true; else x.sex=false; //1 为男,非 1 为女 cin>>x.age>>x.score ;
a[i]=x; //结构赋值 }
cout<<"显示具有 person 结构的"<<n<<"个记录:"<<endl;
for(i=0;i<n;i++) {
cout<<a[i].name<<' ';
if (a[i].sex==true) cout<<"man"<<' ';
else cout<<"woman"<<' ';
cout<<a[i].age<<' '<<a[i].score<<endl;
} }
运行结果如图 4.23 所示。
图 4.23 运行结果
4.6.2 链表基础
结构类型的重要应用之一就是链表。现实生活中存在大量需要动态存储和表示的数据,
如排队、数据排序等。链表是一种动态数据结构,所谓“动态数据结构”是指在程序运行过 程中,数据结构的规模可以根据实际的需要动态变化,从而可以克服数组在使用前必须确定 大小的问题。
1.链表的概念
在结构类型中有一种特殊类型,它除了包含有一般的数据域以外,还包含一个指向自身 结构的指针。这种类型的对象又称节点,每个节点的指针域用来指向下一个节点,由此形成一 个链表,如图 4.24 所示。
例如:
struct item {
(3)循环链表(以单向循环链表为例),如图 4.27 所示。
图 4.27 单向循环链表 对链表的主要操作有以下几种:
(1)建立或生成一个链表。
(2)查找链表元素。
(3)插入一个新元素。
插表头:将每一新节点固定插入至当前已生成链表的表头位置。
插表尾:将每一新节点固定插入至当前已生成链表的表尾位置。
有序表:将每一新节点插入至链表中的适当位置(表头、表中或表尾),以保持链表 的有序性。
(4)删除一个链表节点。
(5)遍历链表,输出链表长度及节点的有关信息。
【例 4.17】输入简化的学生数据,把它们组成线性链表,并输出各学生信息。要求每一 新节点都插入至已生成链表的表头位置。
分析:(1)生成链表:依次键入学号(假设互不相同),创建新的节点,并插入至表头位 置。遇结束标志即止,此时已生成所需链表。
(2)遍历链表:从表头开始,“顺藤摸瓜”遍历所有节点并输出各节点中的有关信息——
学号,直至表尾。
程序如下:
//Ex4_17.cpp
#include "iostream"
#include "cstring"
#include "iomanip"
using namespace std;
void main( ) {
struct item {
int num;
item *next;
};
item *head=NULL,*temp; //初始表头为 NULL int stno;
cout<<"Enter students' numbers,-1 to stop:"<<endl;
head
. 2
. 4
.
5 1 num
next
cin>>stno;
while(stno!=-1) {
temp=new item; //申请新的节点 temp->num=stno; //向节点保存数据
temp->next=head; //初始表尾为 NULL,以后用于节点的连接 head=temp; //更新表头
cin>>stno; //输入新数据 }
cout<<"The output will be:"<<endl;
temp=head; //非空表可略 while(temp!=NULL)
{cout<<setw(6)<<temp->num;
temp=temp->next;}
cout<<endl;
}
运行结果如图 4.28 所示。
图 4.28 运行结果
思考:如要求每一新表元素都插入至已生成链表的表尾位置,该如何修改程序?