资源描述
学校代码: 10128
学 号:
《面向对象得程序设计》实验报告
(
题 目:群体类与群体数据
学生姓名:
学 院:理学院
系 别:数学系
专 业:信息与计算科学
班 级:
任课教师:
二〇一一年 十 一月
一、 实验目得
1、 了解节点类得声明与实现,学习其使用方法
2、 了解链表类得声明与实现,学习其使用方法
3、 了解栈类得声明与实现,学习其使用方法
4、 了解队列类得声明与实现,学习其使用方法
5、 掌握对数组元素排序得方法
6、 掌握对数组元素查找得方法
二、 实验内容
1、、编写程序Node.h实现例9—5得节点类,并编写测试程序lab9_1。cpp,实现链表得基本操作
2、编写程序link.h实现例9-6得链表类,在测试程序lab_2、cpp中声明两个整型链表A与B,分别插入5元素,然后把B中得元素加入A得尾部
3、编写程序queue。h,用链表实现队列(或栈),在测试程序lab9_3.cpp中声明一个整型队列(或栈)对象,插入5个整数,压入队列(或栈),再依次取出并显示出来。
4、将直接插入排序、直接选择排序、冒泡排序、顺序查找函数封装到第九章得数组类中,作为成员函数,实现并测试这个类、
三、 实验程序及结果
1. 程序一
//9_5。h
#ifndef NODE_CLASS
#define NODE_CLASS
//类定义部分
template 〈class T>
class Node
{
private:
Node〈T> *next; //指向后继节点得指针
public:
T data; //数据域
ﻩ // 构造函数
Node (const T& item, Node<T>* ptrnext = NULL);
// 在本节点之后插入一个同类节点p
void InsertAfter(Node〈T> *p);
// 删除本节点得后继节点,并返回其地址
Node〈T〉 *DeleteAfter(void);
// 获取后继节点得地址
Node<T〉 *NextNode(void) const;
};
// 类得实现部分
// 构造函数,初始化数据与指针成员
template <class T〉
Node<T>::Node(const T& item, Node<T>* ptrnext) :
ﻩ data(item), next(ptrnext)
{}
// 返回私有得指针成员
template <class T>
Node〈T> *Node〈T>::NextNode(void) const
{
return next;
}
// 在当前节点之后插入一个节点p
template 〈class T>
void Node〈T〉::InsertAfter(Node<T> *p)
{
p->next = next; //p节点指针域指向当前节点得后继节点
next = p; //当前节点得指针域指向p
}
// 删除当前节点得后继节点,并返回其地址
template <class T〉
Node<T> *Node<T>::DeleteAfter(void)
{
Node<T〉 *tempPtr = next; //将欲删除得节点地址存储到tempPtr中
if (next == NULL) //如果当前节点没有后继节点,则返回NULL
return NULL;
next = tempPtr->next; //使当前节点得指针域指向tempPtr得后继节点
return tempPtr; //返回被删除得节点得地址
}
#endif // NODE_CLASS
//Node、h
#ifndef NODE_LIBRARY
#define NODE_LIBRARY
#include 〈iostream〉
#include <cstdlib〉
#include "9_5、h"
using namespace std;
// 生成结点:创建一个结点,数据成员值为item,指向后继结点得指针值为nextPtr
template 〈class T〉
Node<T> *GetNode(const T& item, Node〈T> *nextPtr = NULL)
{
Node<T〉 *newNode;
// 为新结点分配内存空间,然后将item与NextPtr传递给构造函数
newNode = new Node<T>(item, nextPtr);
if (newNode == NULL) //如果分配内存失败,程序中止
{
cerr << "Memory allocation failure!" 〈< endl;
exit(1);
}
return newNode;
}
enum AppendNewline {noNewline,addNewline};
// 输出链表
template <class T〉
void PrintList(Node<T> *head, AppendNewline addnl = noNewline)
{
// currPtr初始指向表头结点,用于遍历链表
Node<T> *currPtr = head;
// 输出结点数据,直到链表结束
while(currPtr != NULL)
{
// 如果换行标志addl == addNewline,则输出换行符
if(addnl == addNewline)
cout <〈 currPtr->data << endl;
else
cout <〈 currPtr—>data << ” ";
// 使currPtr指向下一个结点
currPtr = currPtr—>NextNode();
}
}
//查找结点
//在指针head所指向得链表中查找数据域等于item得结点
//找到则返回TRUE及其前趋结点得地址,否则返回FALSE
template 〈class T>
int Find(Node<T> *head, T& item, Node〈T>* &prevPtr)
{
ﻩNode<T〉 *currPtr = head; //从第一个结点开始遍历
prevPtr = NULL;
// 通过循环遍历链表,直到表尾
ﻩwhile(currPtr != NULL)
ﻩ{
ﻩ //将item与结点得数据域比较,如果相等,则返回,否则继续处理下一个结点
ﻩ if (currPtr—〉data == item)
ﻩ return 1;
ﻩ prevPtr = currPtr; //记录下当前结点得地址
currPtr = currPtr—〉NextNode();
ﻩ}
ﻩreturn 0; //找不到时
}
//在表头插入结点
template 〈class T>
void InsertFront(Node〈T〉* & head, T item)
{
// 建立新结点,使其指针域指向原链表头结点head,然后更新head
head = GetNode(item,head);
}
//在表尾添加结点
template 〈class T>
void InsertRear(Node〈T>* & head, const T& item)
{
Node〈T〉 *newNode, *currPtr = head;
ﻩ// 如果链表为空,则插入在表头
if (currPtr == NULL)
InsertFront(head,item);
else
{
ﻩ// 寻找指针域为NULL得结点
while(currPtr—>NextNode() != NULL)
currPtr = currPtr->NextNode();
// 建立新结点并插入在表尾(在currPtr之后)
newNode = GetNode(item);
currPtr—>InsertAfter(newNode);
}
}
// 删除链表得第一个结点
template <class T>
void DeleteFront(Node〈T>* & head)
{
Node<T> *p = head; //取得将被删除得结点得地址
if (head != NULL) // 确认链表不空
{
head = head—>NextNode(); // 将表头指针head移向第二个结点
delete p; //删除原第一个结点
}
}
// 删除链表中第一个数据域等于key得结点
template <class T>
void Delete (Node〈T>* & head, T key)
{
// currPtr用于遍历链表,prevPtr跟随其后
Node〈T> *currPtr = head, *prevPtr = NULL;
// 如果链表为空,则返回
if (currPtr == NULL)
return;
//通过循环遍历链表,直到找到数据域为key得结点,或达到表尾
while (currPtr != NULL && currPtr->data != key)
{
// currPtr前行,prevPtr跟随其后
prevPtr = currPtr;
currPtr = currPtr->NextNode();
}
//若 currPtr != NULL,则currPtr指向得结点数据域为key
if (currPtr != NULL)
{
if(prevPtr == NULL) //找到得就是链表第一个结点
head = head->NextNode();
else
// 如果找到得就是第二个以后得结点,调用前趋结点得成员函数删除之
prevPtr->DeleteAfter();
delete currPtr; //释放被删除得结点所占得内存空间
}
}
// 在有序链表中插入一个结点
template <class T>
void InsertOrder(Node<T>* & head, T item)
{
// currPtr用于遍历链表,prevPtr跟随其后
Node<T〉 *currPtr, *prevPtr, *newNode;
// prevPtr == NULL 标志着应插入在表头
prevPtr = NULL;
currPtr = head;
// 通过循环遍历链表,寻找插入点
while (currPtr != NULL)
{
ﻩ// 如果item < 当前结点数据,则插入点应在当前结点之前
ﻩif (item 〈 currPtr—>data)
break;
// currPtr前行,prevPtr跟随其后
prevPtr = currPtr;
currPtr = currPtr->NextNode();
}
// 完成插入
if (prevPtr == NULL) //如果插入点在表头
InsertFront(head,item);
else
{
ﻩ// 在prevPtr指向得结点之后插入新结点
newNode = GetNode(item);
prevPtr—>InsertAfter(newNode);
}
}
//清空链表—-删除链表中得所有结点
template <class T>
void ClearList(Node<T> * &head)
{
Node<T> *currPtr, *nextPtr;
// 边遍历边删除结点
currPtr = head;
while(currPtr != NULL)
{
ﻩ// 记录下一个结点得地址,删除当前结点
nextPtr = currPtr—〉NextNode();
delete currPtr;
currPtr = nextPtr; //使指针currPtr指向下一个结点
}
head = NULL; //将头结点置为NULL,标志着链表为空
}
#endif // NODE_LIBRARY
//lab9_1。cpp
#include <iostream>
#include ”9_5.h"
#include "node、h”
using namespace std;
int main()
{
// 将表头指针置为 NULL
Node<int> *head = NULL, *prevPtr, *delPtr;
int i, key, item;
// 输入10个整数依次向表头插入
for (i=0;i < 10;i++)
{
ﻩ cin〉>item;
InsertFront(head, item);
}
// 输出链表
cout <〈 "List: ";
PrintList(head,noNewline);
cout <〈 endl;
// 输入需要删除得整数
cout << "请输入一个需要删除得整数: ";
cin >> key;
// 查找并删除结点
prevPtr = head;
while (Find(head,key,prevPtr) != NULL)
{
ﻩ if(prevPtr == NULL) //找到得就是链表第一个结点
head = head-〉NextNode();
else
// 如果找到得就是第二个以后得结点,调用前趋结点得成员函数删除之
delPtr=prevPtr->DeleteAfter();
delete delPtr;
ﻩ}
// 输出链表
cout << "List: ";
PrintList(head,noNewline);
cout <〈 endl;
//清空链表
ClearList(head);
}
实验结果如下:
2程序二
//lab9_2、cpp
#include "link。h”
int main()
{
LinkedList<int> A, B;
ﻩfor(int i=0;i〈5;i++)
ﻩ{
A。InsertRear(2*i+1);
ﻩﻩB、InsertRear(2*i+2);
ﻩ}
A、Reset();
cout << ”链表A得元素为:" ;
while(!A.EndOfList())
ﻩ{
ﻩcout << A。Data() << " ";
ﻩA、Next();
ﻩ}
ﻩcout <〈 endl;
B、Reset();
cout 〈< ”链表B得元素为:" ;
ﻩwhile(!B。EndOfList())
ﻩ{
ﻩﻩcout 〈< B。Data() 〈< " ”;
ﻩﻩB、Next();
}
cout << endl;
cout 〈< ”把B中得元素插入A中。。.” << endl;
B、Reset();
ﻩwhile(!B。EndOfList())
ﻩ{
ﻩA、InsertRear(B。Data());
ﻩﻩB。Next();
ﻩ}
A。Reset();
ﻩcout 〈〈 "此时,链表A得元素为:" ;
ﻩwhile(!A。EndOfList())
ﻩ{
ﻩﻩcout 〈〈 A。Data() << " ";
ﻩ A.Next();
}
cout << endl;
}
//link。h
#ifndef LINKEDLIST_CLASS
#define LINKEDLIST_CLASS
#include <iostream〉
#include <cstdlib〉
using namespace std;
#ifndef NULL
const int NULL = 0;
#endif // NULL
#include ”9-3、h
template 〈class T〉
class LinkedList
{
private:
//数据成员:
// 表头与表尾指针
Node〈T〉 *front, *rear;
// 记录表当前遍历位置得指针,由插入与删除操作更新
Node<T> *prevPtr, *currPtr;
// 表中得元素个数
int size;
// 当前元素在表中得位置序号。由函数Reset使用
int position;
//函数成员:
// 生成新节点,数据域为item,指针域为ptrNext
Node<T> *GetNode(const T& item,Node〈T> *ptrNext=NULL);
//释放节点
void FreeNode(Node〈T〉 *p);
// 将链表L 拷贝到当前表(假设当前表为空)。
// 被拷贝构造函数、operator=调用
void CopyList(const LinkedList<T>& L);
public:
// 构造函数
LinkedList(void);
LinkedList(const LinkedList<T〉& L); //拷贝构造函数
// 析构函数
~LinkedList(void);
// 重载赋值运算符
LinkedList<T>& operator= (const LinkedList<T>& L);
// 检查表得状态
int ListSize(void) const; //返回链表中元素个数(size)
int ListEmpty(void) const; //size等于0时返回TRUE,否则返回FALSE
// 遍历表得函数
void Reset(int pos = 0);
//将指针currPtr移动到序号为pos得节点,prevPtr相应移动
// position记录当前节点得序号
void Next(void); //使prevPtr与currPtr移动到下一个节点
int EndOfList(void) const;
// currPtr等于NULL时返回TRUE,否则返回FALSE
int CurrentPosition(void) const; //返回数据成员position
// 插入节点得函数:插入一个数据域为item得节点
void InsertFront(const T& item); //在表头插入
void InsertRear(const T& item); //在表尾添加
void InsertAt(const T& item); //在当前节点之前插入
void InsertAfter(const T& item); //在当前节点之后插入
// 删除节点,释放节点空间,更新prevPtr、currPtr与size
T DeleteFront(void); //删除头节点
void DeleteAt(void); //删除当前节点
// 返回对当前节点成员data得引用(使数据域可以被使用或修改)
T& Data(void);
// 清空链表:释放所有节点得内存空间。被析构函数、operator= 调用
void ClearList(void);
};
template <class T>
Node〈T〉 *LinkedList〈T〉::GetNode(const T& item,
Node〈T〉* ptrNext)
{
Node〈T> *p;
p = new Node<T〉(item,ptrNext);
if (p == NULL)
{
cout << "Memory allocation failure!\n”;
exit(1);
}
return p;
}
template <class T>
void LinkedList<T>::FreeNode(Node<T> *p)
{
delete p;
}
//将L复制到当前链表
template 〈class T〉
void LinkedList<T>::CopyList(const LinkedList<T>& L)
{
//P用来遍历L
Node<T〉 *p = L。front;
int pos;
//将L中得每一个元素插入到当前链表最后
while (p != NULL)
{
InsertRear(p-〉data);
p = p-〉NextNode();
}
//如果链表空,返回
if (position == -1)
return;
//在新链表中重新设置prevPtr与currPtr
prevPtr = NULL;
currPtr = front;
for (pos = 0; pos != position; pos++)
{
prevPtr = currPtr;
currPtr = currPtr—>NextNode();
}
}
//建立一个新链表,即:将有关指针设置为空,size为0,position为-1
template <class T>
LinkedList<T>::LinkedList(void): front(NULL), rear(NULL),
prevPtr(NULL),currPtr(NULL), size(0), position(-1)
{}
template 〈class T>
LinkedList<T>::LinkedList(const LinkedList<T〉& L)
{
front = rear = NULL;
prevPtr = currPtr = NULL;
size = 0;
position = —1;
CopyList(L);
}
template <class T>
void LinkedList<T>::ClearList(void)
{
Node<T〉 *currPosition, *nextPosition;
currPosition = front;
while(currPosition != NULL)
{
ﻩ //取得下一结点得地址并删除当前结点
nextPosition = currPosition->NextNode();
FreeNode(currPosition);
currPosition = nextPosition; // 移动到下一结点
}
front = rear = NULL;
prevPtr = currPtr = NULL;
size = 0;
position = -1;
}
template <class T>
LinkedList<T>::~LinkedList(void)
{
ClearList();
}
template <class T>
LinkedList<T>& LinkedList〈T>::operator=
(const LinkedList〈T>& L)
{
if (this == &L) // 不能将链表赋值给它自身
return *this;
ClearList();
CopyList(L);
return *this;
}
template <class T>
int LinkedList〈T〉::ListSize(void) const
{
return size;
}
template 〈class T〉
int LinkedList<T>::ListEmpty(void) const
{
return size == 0;
}
//将prevPtr与currPtr向前移动一个结点
template <class T〉
void LinkedList〈T〉::Next(void)
{
if (currPtr != NULL)
{
prevPtr = currPtr;
currPtr = currPtr->NextNode();
position++;
}
}
// 如果已经遍历完链表则返回True
template 〈class T>
int LinkedList<T>::EndOfList(void) const
{
return currPtr == NULL;
}
// 返回当前结点得位置
template 〈class T>
int LinkedList〈T>::CurrentPosition(void) const
{
return position;
}
//将链表当前位置设置为pos
template 〈class T>
void LinkedList<T>::Reset(int pos)
{
int startPos;
// 如果链表为空,返回
if (front == NULL)
return;
// 如果位置不合法,中止程序
if (pos 〈 0 || pos > size-1)
{
cerr << ”Reset: Invalid list position: " 〈< pos
<< endl;
return;
}
// 设置与遍历链表有关得成员
if(pos == 0)
{
// 将指针重新设置到表头
prevPtr = NULL;
currPtr = front;
position = 0;
}
else
// 重新设置 currPtr, prevPtr, 与 position
{
currPtr = front—>NextNode();
prevPtr = front;
startPos = 1;
ﻩ //移动指针直到 position == pos
ﻩ for(position=startPos; position != pos; position++)
{
ﻩ // 向前移动遍历指针
ﻩ prevPtr = currPtr;
currPtr = currPtr—>NextNode();
}
}
}
//返回一个当前结点数值得引用
template <class T〉
T& LinkedList〈T>::Data(void)
{
// 如果链表为空或已经完成遍历则出错
if (size == 0 || currPtr == NULL)
{
cerr <〈 "Data: invalid reference!" <〈 endl;
exit(1);
}
return currPtr->data;
}
// 将item插入在表头
template <class T>
void LinkedList〈T〉::InsertFront(const T& item)
{
// 如果链表不空则调用Reset
if (front != NULL)
Reset();
InsertAt(item); // 在表头插入
}
// 在表尾插入
template 〈class T〉
void LinkedList<T〉::InsertRear(const T& item)
{
Node<T〉 *newNode;
prevPtr = rear;
newNode = GetNode(item); // 创建新结点
if (rear == NULL) ﻩﻩﻩ// 如果表空则插入在表头
front = rear = newNode;
else
{
rear->InsertAfter(newNode);
rear = newNode;
}
currPtr = rear;
position = size;
size++;
}
// 将item插入在链表当前位置
template 〈class T〉
void LinkedList〈T>::InsertAt(const T& item)
{
Node〈T> *newNode;
// 两种情况: 插入在链表头或链表之中
if (prevPtr == NULL)
{
// 插入在链表头,包括将结点插入到空表中
newNode = GetNode(item,front);
front = newNode;
}
else
{
// 插入到链表之中. 将结点置于prevPtr之后
newNode = GetNode(item);
prevPtr->InsertAfter(newNode);
}
// 如果prevPtr == rear, 说明正在向空表中插入,
// 或者就是插入到非空表得表尾;更新rear 与 position
if (prevPtr == rear)
{
rear = newNode;
position = size;
}
//更新currPtr并且使size增值
currPtr = newNode;
size++;
}
// 将item 插入到链表当前位置之后
template 〈class T>
void LinkedList<T〉::InsertAfter(const T& item)
{
Node〈T> *p;
p = GetNode(item);
if (front == NULL) // 向空表中插入
{
front = currPtr = rear = p;
position = 0;
}
else
{
// 插入到最后一个结点之后
if (currPtr == NULL)
currPtr = prevPtr;
currPtr—>InsertAfter(p);
if (currPtr == rear)
{
rear = p;
position = size;
}
else
position++;
prevPtr = currPtr;
currPtr = p;
}
size++; // 使链表长度增值
}
// 删除表头结点
template 〈class T>
T LinkedList<T>::DeleteFront(void)
{
T item;
Reset();
if (front == NULL)
{
cerr 〈< "Invalid deletion!" 〈< endl;
exit(1);
}
item = currPtr->data;
DeleteAt();
retur
展开阅读全文