实验九 模板类的构造
目录
9.1 实验目的
1.理解和应用类模板和函数模板;
2.复习数据结构的相关知识;
3.学习用C++的编程思想实现链表类。
9.2 实验内容
9.2.1程序阅读
1.理解下面的动态数组类模板,它由一系列位置连续、任意数量相同类型的元素组成,其元素个数可在程序运行时改变,并完成该类中没有完成的成员函数(不允许改变已有代码),并设计主函数,实现对该模板类的功能测试。
#include <iostream>
#include <stdlib.h>
//容错处理
enum ErrorType
{
invalidArraySize,memoryAllocatetionError,indexOutOfRang
};
char *errorMsg[] =
{
"Invalid array size",
"Memory allocation error",
"Invalid index"
};
template <class T>
class Array
{
private:
T* alist;
int size;
void Error(ErrorType error) const;//输出错误信息
public:
Array(int sz=50);//构造函数
Array(const Array<T>& X);//拷贝构造函数
~Array(void);//析构函数
Array<T>& operator=(const Array<T>& rhs);//重载赋值运算符
T& operator[](int i);//重载下标运算符
int GetSize(void) const;//获取数组大小
void Resize(int sz);//重新设置数组大小
};
template <class T>
Array<T>::Array(int sz)
{
if(sz <= 0)
Error(invalidArraySize);
size = sz;
alist = new T[size];
if(alist == 0)
Error(memoryAllocatetionError);
}
template <class T>
Array<T>::Array(const Array<T>& X)
{
int n = X.size;
size = n;
alist = new T[n];
if(alist == 0)
Error(memoryAllocatetionError);
T* srcptr = X.alist;
T* destptr = alist;
while(n--)
*destptr++ = *srcptr++;
}
template<class T>
Array<T>::~Array()
{
delete[] alist;
}
template <class T>
Array<T>& Array<T>::operator=(const Array<T> &rhs)
{
int n = rhs.size;
if(size != n)
{
delete[] alist;
alist = new T[n];
if(alist == 0)
Error(memoryAllocatetionError);
size = n;
}
T* destptr = alist;
T* srcptr = rhs.alist;
while(n--)
*destptr++ = *srcptr++;
return *this;
}
template<class T>
T& Array<T>::operator[](int n)
{
if(n < 0 || n > size-1)
Error(indexOutOfRang);
return alist[n];
}
void main()
{
}
答:
#include <iostream>
#include <stdlib.h>
using namespace std;
//容错处理
enum ErrorType{
invalidArraySize,memoryAllocatetionError,indexOutOfRang
};
char *errorMsg[] = {
"Invalid array size",
"Memory allocation error",
"Invalid index"
};
template <class T>
class Array{
private:
T* alist;
int size;
void Error(ErrorType error) const{//输出错误信息
cout<<errorMsg[error]<<endl;
exit(-1);
};
public:
Array(int sz=50);//构造函数
Array(const Array<T>& X);//拷贝构造函数
~Array(void);//析构函数
Array<T>& operator=(const Array<T>& rhs);//重载赋值运算符
T& operator[](int i);//重载下标运算符
int GetSize(void) const;//获取数组大小
void Resize(int sz);//重新设置数组大小
};
template <class T>
Array<T>::Array(int sz){
if(sz <= 0)
Error(invalidArraySize);
size = sz;
alist = new T[size];
if(alist == 0)
Error(memoryAllocatetionError);
}
template <class T>
Array<T>::Array(const Array<T>& X){
int n = X.size;
size = n;
alist = new T[n];
if(alist == 0)
Error(memoryAllocatetionError);
T* srcptr = X.alist;
T* destptr = alist;
while(n--)
*destptr++ = *srcptr++;
}
template<class T>
Array<T>::~Array(){
delete[] alist;
}
template <class T>
Array<T>& Array<T>::operator=(const Array<T> &rhs){
int n = rhs.size;
if(size != n){
delete[] alist;
alist = new T[n];
if(alist == 0)
Error(memoryAllocatetionError);
size = n;
}
T* destptr = alist;
T* srcptr = rhs.alist;
while(n--)
*destptr++ = *srcptr++;
return *this;
}
template<class T>
T& Array<T>::operator[](int n){
if(n < 0 || n > size-1)
Error(indexOutOfRang);
return alist[n];
}
template<class T>
int Array<T>::GetSize(void)const{
return size;
}
template<class T>
void Array<T>::Resize(int sz){
if(sz <= 0)
Error(invalidArraySize);
else if(sz == 0)
return;
T* newlist = new T[sz];
if(newlist == 0)
Error(memoryAllocatetionError);
int n = min(size,sz);
T* destptr = newlist;
T* srcptr = alist;
while(n--)
*destptr++ = *srcptr++;
delete[] alist;
alist=newlist;
size=sz;
}
int main(){
Array<int> a(10);
for(int i=0;i<100;i++){
if(i==a.GetSize()){
a.Resize(i+10);
}
a[i]=i;
}
Array<int> b;
b=a;
cout<<"a[10]: "<<a[10]<<endl;
cout<<"b[10]: "<<b[10]<<endl;
}
9.2.2 程序设计
1.设计一个通用链表类,要求如下:
a.数据成员包含头指针、尾指针、链表中节点个数、顺序访问中当前节点指针和当前节点前一个节点的指针;
b.主要的成员函数包含:生成节点(在链表头、尾以及任意位置)、插入节点、删除节点、访问/修改节点、遍历链表,以及一些辅助函数等;
c.能实现两个链表的复制;
d.能实现两个链表对象的赋值;
e.在测试程序中定义两个整型链表A和B,本别插入5个元素,然后把B中的元素加入A的尾部。
答:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
template<class T>
class node{//节点
public:
T data=0;
node *next;
};
template<class T>
class LinkList{
private:
node<T> *head;//头节点
node<T> *end;//尾节点
int size;//节点个数
node<T> *now;//当前指针
node<T> *last;//前一个指针
public:
LinkList(int n);
~LinkList();
void Generate_head();//生成默认data为0
void Generate_end();
void Generate_i(int i);
void Insert(int i,node<T> *s);
void Delete(int i);
node<T>* getNode(int i);
void overAll();
node<T>* getHead();
int getSize();
void operator=(LinkList<T> &t);
void Insert_Link(int i,LinkList<T> &t);
void Insert_Link_End(LinkList<T> &t);
};
template<class T>
LinkList<T>::LinkList(int n=0){
size=n;
head=new node<T>;
end=head;
for(int i=1;i<=n;i++){
node<T> *s=new node<T>;
end->next=s;
end=s;
}
}
template<class T>
LinkList<T>::~LinkList(){
delete[] head;
delete[] end;
delete[] now;
delete[] last;
}
template<class T>
void LinkList<T>::operator=(LinkList<T> &t){
if(getSize()!=t.getSize()){
cout<<"Error: Size not equal! "<<endl;
return;
}
int n=getSize();
for(int i=1;i<=n;i++){
getNode(i)->data=t.getNode(i)->data;
}
}
template<class T>
int LinkList<T>::getSize(){
return size;
}
template<class T>
node<T>* LinkList<T>::getNode(int i){
if(i<1 || i >size){
cout<<"Error: i out of range!"<<endl;
return head;
}
node<T> *t=head;
for(int j=1;j<=i-1;j++)
t=t->next;
return t;
}
template<class T>
void LinkList<T>::Generate_head(){//头生成一个
size++;
node<T> *s=new node<T>;
s->next=head;
head=s;
}
template<class T>
void LinkList<T>::Generate_end(){//尾生成一个
size++;
node<T> *s=new node<T>;
end->next=s;
end=s;
}
template<class T>
void LinkList<T>::Generate_i(int i){//在第i个位置生成一个
if(i<1 || i >size){
cout<<"Error: i out of range!"<<endl;
return;
}
size++;
node<T> *t=getNode(i-1);
node<T> *s=new node<T>;
s->next=t->next;
t->next=s;
}
template<class T>
node<T>* LinkList<T>::getHead(){
return head;
}
template<class T>
void LinkList<T>::Insert(int i,node<T> *s){
if(i<1 || i >size){
cout<<"Error: i out of range!"<<endl;
return;
}
size++;
node<T> *t=getNode(i-1);
s->next=t->next;
t->next=s;
}
template<class T>
void LinkList<T>::Delete(int i){
if(i<1 || i >size){
cout<<"Error: i out of range!"<<endl;
return;
}
if(i==1){
node<T> *s=head;
head=head->next;
delete[] s;
}else{
node<T> *s=getNode(i);
node<T> *t=getNode(i-1);
t->next=s->next;
delete[] s;
}
size--;
}
template<class T>
void LinkList<T>::Insert_Link(int i,LinkList<T> &t){
int n=t.getSize();
for(int j=1;j<=n;j++){
node<T> *s=new node<T>;
s->data=t.getNode(j)->data;
this->Insert(i++,s);
}
}
template<class T>
void LinkList<T>::Insert_Link_End(LinkList<T> &t){
int i=size+1;
size+=t.getSize();
Insert_Link(i,t);
size-=t.getSize();
}
template<class T>
void LinkList<T>::overAll(){
int n=getSize();
for(int i=1;i<=n;i++)
cout<<getNode(i)->data<<" ";
cout<<endl;
}
int main(){
LinkList<int> LL(5);
for(int i=1;i<=5;i++)
LL.getNode(i)->data=i;
cout<<"*LinkList 创建"<<endl;
LL.overAll();
cout<<"*头部生成节点"<<endl;
LL.Generate_head();
LL.overAll();
cout<<"*尾部生成节点"<<endl;
LL.Generate_end();
LL.overAll();
cout<<"*任意位置生成节点"<<endl;
LL.Generate_i(3);
LL.overAll();
cout<<"*删除节点"<<endl;
LL.Delete(1);
LL.Delete(2);
LL.Delete(6);
LL.overAll();
cout<<"*运算符=重载"<<endl;
LinkList<int> A(5);
A=LL;
A.overAll();
LinkList<int> B(5);
for(int i=1;i<=5;i++)
B.getNode(i)->data = -1*i;
cout<<"*链表尾插入"<<endl;
LL.Insert_Link_End(B);//按题目要求 加入尾部的测试
LL.overAll();
return 0;
}
9.3思考题
1.根据数据结构和类模板知识,定义一个通用队列(先进先出)类并加以实现,编写主函数进行测试;
答:参照课本P510
#include<iostream>
#include<cstdlib>
using namespace std;
const int MAXSIZE = 1000;
template <class T>
class Queue{
private:
int front,rear,count;
T qlist[MAXSIZE];
public:
Queue(void);
void Insert(const T& item);
T Delete(void);
T getFront(void) const;
int getLength(void) const;
bool isEmpty(void) const;
bool isFull(void) const;
};
template <class T>
Queue<T>::Queue(void):front(0),rear(0),count(0){
}
template <class T>
void Queue<T>::Insert(const T& item){
if(count==MAXSIZE){
cout<<"Queue Overflow!"<<endl;
exit(1);
}
count++;
qlist[rear]=item;
rear=(rear+1)%MAXSIZE;
}
template <class T>
T Queue<T>::Delete(void){
T temp;
if(count==0){
cout<<"Delete from empty queue!"<<endl;
exit(1);
}
temp=qlist[front];
count--;
front=(front+1)%MAXSIZE;
return temp;
}
template <class T>
T Queue<T>::getFront(void) const{
return qlist[front];
}
template <class T>
int Queue<T>::getLength(void) const{
return count;
}
template <class T>
bool Queue<T>::isEmpty(void) const{
return count==0;
}
template <class T>
bool Queue<T>::isFull(void) const{
return count==MAXSIZE;
}
int main(){
Queue<int>q;
q.Insert(1);
q.Insert(2);
q.Insert(3);
q.Insert(4);
q.Insert(5);
cout<<"The front is "<<q.getFront()<<endl;
while(!q.isEmpty()){
cout<<"The length is "<<q.getLength()<<endl;
cout<<"The front is "<<q.getFront()<<endl;
q.Delete();
}
int i=1;
while(!q.isFull()){
q.Insert(i++);
}
cout<<"The length is "<<q.getLength()<<endl;
return 0;
}
2.根据数据结构和类模板知识,定义一个通用栈(后进先出)类并加以实现,编写主函数进行测试。
答:
#include<iostream>
#include<cstdlib>
using namespace std;
const int MAXSIZE = 1000;
template <class T>
class Stack{
private:
int top,count;
T slist[MAXSIZE];
public:
Stack(void);
void Push(const T& item);
T Pop(void);
T getTop(void) const;
int getCount(void) const;
bool isEmpty(void) const;
bool isFull(void) const;
};
template <class T>
Stack<T>::Stack(void):top(0),count(0){
}
template <class T>
void Stack<T>::Push(const T& item){
if(count==MAXSIZE){
cout<<"Stack Overflow!"<<endl;
exit(1);
}
count++;
slist[top++]=item;
}
template <class T>
T Stack<T>::Pop(void){
T temp;
if(count==0){
cout<<"Delete from empty Stack!"<<endl;
exit(1);
}
temp=slist[top--];
count--;
return temp;
}
template <class T>
T Stack<T>::getTop(void) const{
return slist[top-1];
}
template <class T>
int Stack<T>::getCount(void) const{
return count;
}
template <class T>
bool Stack<T>::isEmpty(void) const{
return count==0;
}
template <class T>
bool Stack<T>::isFull(void) const{
return count==MAXSIZE;
}
int main(){
Stack<int>s;
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
s.Push(5);
cout<<"The top is "<<s.getTop()<<endl;
while(!s.isEmpty()){
cout<<"The length is "<<s.getCount()<<endl;
cout<<"The top is "<<s.getTop()<<endl;
s.Pop();
}
int i=1;
while(!s.isFull()){
s.Push(i++);
}
cout<<"The length is "<<s.getCount()<<endl;
return 0;
}