⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter9.htm

📁 为清华大学出版社 C++课后答案
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<!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>第 九 章&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 群体类</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 &lt;iostream.h&gt;<br>
  #include &lt;stdlib.h&gt;</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 &lt;class T&gt; <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&lt;T&gt;&amp; A); //拷贝构造函数<br>
  ~Array(void); //析构函数<br>
  <br>
  //重载"="使数组对象可以整体赋值<br>
  Array&lt;T&gt;&amp; operator= (const Array&lt;T&gt;&amp; rhs); <br>
  <br>
  //重载"[]"与T*,使Array对象可以起到C++普通数组的作用<br>
  T&amp; 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 &lt;class T&gt;<br>
  void Array&lt;T&gt;::Error(ErrorType error, int badIndex) const<br>
  {<br>
  cout &lt;&lt; errorMsg[error]; //根据错误类型,输出相应的错误信息<br>
  // for indexOutOfRange, print the bad index<br>
  if (error == indexOutOfRange)<br>
  cout &lt;&lt; badIndex; //如果是下标越界错,输出错误的下标<br>
  cout &lt;&lt; endl;<br>
  exit(1);<br>
  }</p>
<p class="style3">// 构造函数<br>
  template &lt;class T&gt;<br>
  Array&lt;T&gt;::Array(int sz)<br>
  {<br>
  if (sz &lt;= 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 &lt;class T&gt;<br>
  Array&lt;T&gt;::~Array(void)<br>
  { <br>
  delete [] alist;<br>
  }</p>
<p class="style3">// 拷贝构造函数<br>
  template &lt;class T&gt;<br>
  Array&lt;T&gt;::Array(const Array&lt;T&gt;&amp; 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 &lt;class T&gt;<br>
  Array&lt;T&gt;&amp; Array&lt;T&gt;::operator= (const Array&lt;T&gt;&amp; 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 &lt;class T&gt;<br>
  T&amp; Array&lt;T&gt;::operator[] (int n)<br>
  {<br>
  // 检查下标是否越界<br>
  if (n &lt; 0 || n &gt; size-1)<br>
  Error(indexOutOfRange,n);<br>
  // 返回下标为n的数组元素<br>
  return alist[n];<br>
  }</p>
<p class="style3">//重载指针转换操作符,使指向T类对象的指针成为当前对象中私有数组的首地址。<br>
  //因而可以象使用普通数组首地址一样使用T类型指针<br>
  template &lt;class T&gt;<br>
  Array&lt;T&gt;::operator T* (void) const<br>
  {<br>
  // 返回当前对象中私有数组的首地址<br>
  return alist;<br>
  }</p>
<p class="style3">//取当前数组的大小<br>
  template &lt;class T&gt;<br>
  int Array&lt;T&gt;::ListSize(void) const<br>
  {<br>
  return size;<br>
  }</p>
<p class="style3">// 将数组大小修改为sz<br>
  template &lt;class T&gt;<br>
  void Array&lt;T&gt;::Resize(int sz)<br>
  {<br>
  // 检查是否sz&lt;= 0<br>
  if (sz &lt;= 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 &lt;= 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 &lt;iostream.h&gt;<br>
  #include &lt;iomanip.h&gt;</p>
<p class="style3">void main()<br>
  {<br>
  int n;<br>
  double AverScore,TotalScore = 0;<br>
  cout &lt;&lt; "请输入学生人数:";<br>
  cin &gt;&gt; n;<br>
  Array&lt;float&gt; Score(n);<br>
  for (int i=0; i&lt;n; i++)<br>
  {<br>
  cout &lt;&lt; "请输入第" &lt;&lt; i+1 &lt;&lt;"个学生的课程A成绩(0~100):";<br>
  cin &gt;&gt; Score[i];<br>
  TotalScore += Score[i];<br>
  }<br>
  AverScore = TotalScore/n;<br>
  cout &lt;&lt; "平均成绩为" &lt;&lt; setprecision(4) &lt;&lt; AverScore &lt;&lt; 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 &lt;class T&gt;<br>
  class DNode<br>
  {<br>
  private:<br>
  // circular links to the left and right<br>
  DNode&lt;T&gt; *left;<br>
  DNode&lt;T&gt; *right;<br>
  public: <br>
  // data is public <br>
  T data;<br>
  <br>
  // constructors<br>
  DNode(void); <br>
  DNode (const T&amp; item);<br>
  <br>
  <br>
  // list modification methods<br>
  void InsertRight(DNode&lt;T&gt; *p);<br>
  void InsertLeft(DNode&lt;T&gt; *p);<br>
  DNode&lt;T&gt; *DeleteNode(void);<br>
  <br>
  <br>
  // obtain address of the next node to the left or right<br>
  DNode&lt;T&gt; *NextNodeRight(void) const;<br>
  DNode&lt;T&gt; *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 &lt;class T&gt;<br>
  DNode&lt;T&gt;::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 &lt;class T&gt;<br>
  DNode&lt;T&gt;::DNode(const T&amp; 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 &lt;class T&gt;<br>
  void DNode&lt;T&gt;::InsertRight(DNode&lt;T&gt; *p)<br>
  {<br>
  // link p to its successor on the right<br>
  p-&gt;right = right;<br>
  right-&gt;left = p;<br>
  <br>
  // link p to the current node on its left<br>
  p-&gt;left = this;<br>
  right = p;<br>
  }</p>
<p class="style3">// insert a node p to the left of current node<br>
  template &lt;class T&gt;<br>
  void DNode&lt;T&gt;::InsertLeft(DNode&lt;T&gt; *p)<br>
  {<br>
  // link p to its successor on the left<br>
  p-&gt;left = left;<br>
  left-&gt;right = p;<br>
  <br>
  // link p to the current node on its right<br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -