📄 chapter9.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
<style type="text/css">
<!--
.style1 {
color: #FF0000;
font-size: 16px;
font-style: italic;
}
.style2 {
font-size: 14px;
font-weight: bold;
font-family: "宋体";
}
.style3 {font-family: "宋体"; font-size: 14px;}
-->
</style>
</head>
<body>
<p class="style3"><span
class=style1><strong>第 九 章 群体类</strong></span><br>
</p>
<p class="style3"><span class="style2">9-1 程序中提示输入班级中的学生人数N,再依次提示用户输入N个人在课程A的考试成绩,然后计算出平均成绩,显示出来。请使用教材第9章中的数组类模板Array定义浮点型数组储存考试成绩值。</span><br>
</span></p>
<p class="style3">解: <br>
//array.h即为教材中的例程9-2,参见教材第9章<br>
//array.h<br>
#ifndef ARRAY_CLASS<br>
#define ARRAY_CLASS </p>
<p class="style3">#include <iostream.h><br>
#include <stdlib.h></p>
<p class="style3">#ifndef NULL<br>
const int NULL = 0;<br>
#endif // NULL</p>
<p class="style3">//错误类型集合,共有三种类型的错误:数组大小错误、内存分配错误和下标越界<br>
enum ErrorType <br>
{invalidArraySize, memoryAllocationError, indexOutOfRange};</p>
<p class="style3">//错误信息<br>
char *errorMsg[] =<br>
{<br>
"Invalid array size", "Memory allocation error",<br>
"Invalid index: "<br>
};</p>
<p class="style3">//数组类模板<br>
template <class T> <br>
class Array<br>
{<br>
private:<br>
T* alist; //T类型指针,用于存放动态分配的数组内存首地址<br>
int size; //数组大小(元素个数)<br>
<br>
// 错误处理函数<br>
void Error(ErrorType error,int badIndex=0) const;<br>
<br>
public:<br>
Array(int sz = 50); //构造函数<br>
Array(const Array<T>& A); //拷贝构造函数<br>
~Array(void); //析构函数<br>
<br>
//重载"="使数组对象可以整体赋值<br>
Array<T>& operator= (const Array<T>& rhs); <br>
<br>
//重载"[]"与T*,使Array对象可以起到C++普通数组的作用<br>
T& operator[](int i); <br>
operator T* (void) const;<br>
<br>
int ListSize(void) const; // 取数组的大小<br>
<br>
void Resize(int sz); // 修改数组的大小<br>
};</p>
<p class="style3">//以下为类成员函数的实现</p>
<p class="style3">//模扳函数Error实现输出错误信息的功能<br>
template <class T><br>
void Array<T>::Error(ErrorType error, int badIndex) const<br>
{<br>
cout << errorMsg[error]; //根据错误类型,输出相应的错误信息<br>
// for indexOutOfRange, print the bad index<br>
if (error == indexOutOfRange)<br>
cout << badIndex; //如果是下标越界错,输出错误的下标<br>
cout << endl;<br>
exit(1);<br>
}</p>
<p class="style3">// 构造函数<br>
template <class T><br>
Array<T>::Array(int sz)<br>
{<br>
if (sz <= 0) //sz为数组大小(元素个数),若小于0,则输出错误信息<br>
Error(invalidArraySize);<br>
<br>
size = sz; // 将元素个数赋值给变量size<br>
alist = new T[size]; //动态分配size个T类型的元素空间<br>
if (alist == NULL) //如果分配内存不成功,输出错误信息<br>
Error(memoryAllocationError);<br>
}</p>
<p class="style3">// 析构函数<br>
template <class T><br>
Array<T>::~Array(void)<br>
{ <br>
delete [] alist;<br>
}</p>
<p class="style3">// 拷贝构造函数<br>
template <class T><br>
Array<T>::Array(const Array<T>& X)<br>
{<br>
//从对象X取得数组大小,并赋值给当前对象的成员<br>
int n = X.size; <br>
size = n;<br>
<br>
//为对象申请内存并进行出错检查<br>
alist = new T[n]; // 动态分配n个T类型的元素空间<br>
if (alist == NULL) //如果分配内存不成功,输出错误信息<br>
Error(memoryAllocationError);<br>
<br>
// 从对象X复制数组元素到本对象 <br>
T* srcptr = X.alist; // X.alist是对象X的数组首地址<br>
T* destptr = alist; // alist是本对象中的数组首地址<br>
while (n--) // 逐个复制数组元素<br>
*destptr++ = *srcptr++;<br>
}</p>
<p class="style3">// 重载"="运算符,将对象rhs赋值给本对象。实现对象之间的整体赋值<br>
template <class T><br>
Array<T>& Array<T>::operator= (const Array<T>& rhs)<br>
{<br>
int n = rhs.size; // 取rhs的数组大小<br>
<br>
//如果本对象中数组大小与rhs不同,则删除数组原有内存,然后重新分配<br>
if (size != n)<br>
{<br>
delete [] alist; // 删除数组原有内存<br>
alist = new T[n]; // 重新分配n个元素的内存<br>
if (alist == NULL) //如果分配内存不成功,输出错误信息<br>
Error(memoryAllocationError);<br>
size = n; //记录本对象的数组大小<br>
}<br>
<br>
// 从rhs向本对象复制元素<br>
T* destptr = alist;<br>
T* srcptr = rhs.alist;<br>
while (n--) <br>
*destptr++ = *srcptr++;<br>
<br>
// 返回指向本对象的指针<br>
return *this;<br>
}</p>
<p class="style3">// 重载下标操作符,实现与普通数组一样通过下标访问元素,并且具有越界检查功能<br>
template <class T><br>
T& Array<T>::operator[] (int n)<br>
{<br>
// 检查下标是否越界<br>
if (n < 0 || n > size-1)<br>
Error(indexOutOfRange,n);<br>
// 返回下标为n的数组元素<br>
return alist[n];<br>
}</p>
<p class="style3">//重载指针转换操作符,使指向T类对象的指针成为当前对象中私有数组的首地址。<br>
//因而可以象使用普通数组首地址一样使用T类型指针<br>
template <class T><br>
Array<T>::operator T* (void) const<br>
{<br>
// 返回当前对象中私有数组的首地址<br>
return alist;<br>
}</p>
<p class="style3">//取当前数组的大小<br>
template <class T><br>
int Array<T>::ListSize(void) const<br>
{<br>
return size;<br>
}</p>
<p class="style3">// 将数组大小修改为sz<br>
template <class T><br>
void Array<T>::Resize(int sz)<br>
{<br>
// 检查是否sz<= 0<br>
if (sz <= 0) <br>
Error(invalidArraySize);<br>
// 如果指定的大小与原有大小一样,什么也不做<br>
if (sz == size)<br>
return;<br>
<br>
// 申请新的数组内存,并测试是否申请成功<br>
T* newlist = new T[sz];<br>
if (newlist == NULL)<br>
Error(memoryAllocationError);<br>
<br>
// 将sz与size中较小的一个赋值给n<br>
int n = (sz <= size) ? sz : size;<br>
<br>
// 将原有数组中前n个元素复制到新数组中<br>
T* srcptr = alist; // 原数组alist的首地址<br>
T* destptr = newlist; // 新数组newlist的首地址<br>
while (n--) // 复制数组元素<br>
*destptr++ = *srcptr++;<br>
<br>
// 删除原数组<br>
delete[] alist;<br>
<br>
// 使alist 指向新数组,并更新size<br>
alist = newlist;<br>
size = sz;<br>
}</p>
<p class="style3">#endif // ARRAY_CLASS</p>
<p class="style3">//test9_1.cpp<br>
#include <iostream.h><br>
#include <iomanip.h></p>
<p class="style3">void main()<br>
{<br>
int n;<br>
double AverScore,TotalScore = 0;<br>
cout << "请输入学生人数:";<br>
cin >> n;<br>
Array<float> Score(n);<br>
for (int i=0; i<n; i++)<br>
{<br>
cout << "请输入第" << i+1 <<"个学生的课程A成绩(0~100):";<br>
cin >> Score[i];<br>
TotalScore += Score[i];<br>
}<br>
AverScore = TotalScore/n;<br>
cout << "平均成绩为" << setprecision(4) << AverScore << endl;<br>
}</p>
<p class="style3">程序运行输出:<br>
请输入学生人数:3<br>
请输入第1个学生的课程A成绩(0~100):80<br>
请输入第2个学生的课程A成绩(0~100):80<br>
请输入第3个学生的课程A成绩(0~100):81<br>
平均成绩为80.33<br>
</p>
<p class="style3"><strong>9-2 链表中的一个节点包含哪些数据成员?单链表和双向链表的区别是什么?</strong><br>
</p>
<p class="style3">解: <br>
链表是由系列结点组成的,每一个结点包括数据域和指向链表中其它结点的指针(即下一个结点的地址)。每个结点中只有一个指向后继结点指针的链表称为单链表。如果链表中每个结点中有两个用于连接其它结点的指针,一个指向前趋结点(称前趋指针),另一个指向后继结点(称后继指针),这样的链表称为双向链表。<br>
</p>
<p class="style3"><strong>9-3 链表中元素的最大数目为多少?</strong><br>
</p>
<p class="style3">解:<br>
链表中元素的最大数目没有固定限制,只取决于可用的内存数量。<br>
</p>
<p class="style3"><strong>9-4 在双向链表中使用的节点类与单链表中使用的节点类相比,应有何不同?试定义并实现双向链表中使用的节点类DNODE。</strong><br>
</p>
<p class="style3">解: <br>
每一个结点包括数据域和指向链表中其它结点的指针(即下一个结点的地址),单链表中使用的节点类中每个结点中只有一个指向后继结点指针;在双向链表中使用的节点类中有两个用于连接其它结点的指针,一个指向前趋结点(称前趋指针),另一个指向后继结点(称后继指针)。双向链表中使用的节点类可如下定义:<br>
//dnode.h<br>
#ifndef DOUBLY_LINKED_NODE_CLASS<br>
#define DOUBLY_LINKED_NODE_CLASS</p>
<p class="style3">template <class T><br>
class DNode<br>
{<br>
private:<br>
// circular links to the left and right<br>
DNode<T> *left;<br>
DNode<T> *right;<br>
public: <br>
// data is public <br>
T data;<br>
<br>
// constructors<br>
DNode(void); <br>
DNode (const T& item);<br>
<br>
<br>
// list modification methods<br>
void InsertRight(DNode<T> *p);<br>
void InsertLeft(DNode<T> *p);<br>
DNode<T> *DeleteNode(void);<br>
<br>
<br>
// obtain address of the next node to the left or right<br>
DNode<T> *NextNodeRight(void) const;<br>
DNode<T> *NextNodeLeft(void) const;<br>
};</p>
<p class="style3">// constructor that creates an empty list and<br>
// leaves the data uninitialized. use for header<br>
template <class T><br>
DNode<T>::DNode(void)<br>
{<br>
// initialize the node so it points to itself<br>
left = right = this;<br>
}</p>
<p class="style3">// constructor that creates an empty list and initializes data<br>
template <class T><br>
DNode<T>::DNode(const T& item)<br>
{<br>
// set node to point to itself and initialize data<br>
left = right = this;<br>
data = item;<br>
}</p>
<p class="style3">// insert a node p to the right of current node<br>
template <class T><br>
void DNode<T>::InsertRight(DNode<T> *p)<br>
{<br>
// link p to its successor on the right<br>
p->right = right;<br>
right->left = p;<br>
<br>
// link p to the current node on its left<br>
p->left = this;<br>
right = p;<br>
}</p>
<p class="style3">// insert a node p to the left of current node<br>
template <class T><br>
void DNode<T>::InsertLeft(DNode<T> *p)<br>
{<br>
// link p to its successor on the left<br>
p->left = left;<br>
left->right = p;<br>
<br>
// link p to the current node on its right<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -