一、要求:
- 完成有理数的类定义以及有理数逻辑运算函数
class Rational{
friend bool operator<(const Rational& r1, const Rational& r2) {}
friend bool operator<=(const Rational& r1, const Rational& r2) {}
friend bool operator>(const Rational& r1, const Rational& r2) {}
friend bool operator>=(const Rational& r1, const Rational& r2) {}
friend bool operator==(const Rational& r1, const Rational& r2) {}
friend bool operator!=(const Rational& r1, const Rational& r2) {}
public:
int N; //分子
int D; //分母, 要求大于0
Rational() {} //default constructor
Rational(int n){} //constructor for integer value
Rational(int n, int d) {} //normal constructor
Rational(const Rational& r){} //copy constructor
Rational& operator=(const Rational& r) {} // assignment override
};
- 创建有理数的最小堆,实现siftdown, siftup, insert等功能
3. 实现基于最小堆的堆排序,按从小到大的顺序输出有理数
4. 为在线测评系统检测程序的运行,对程序文档及IO做如下规范:
(1)所有类、函数及主程序都写在一个单cpp文档里,不能有其他include用的.h或.cpp文档
(2)程序不能输出任何提示用的字符串
(3)输入: 第一行包含一个整数T (1T105);接下来的T行,每一行有两个整数n, d (|n|<103, 0<d<103),用空格隔开,表示输入的有理数的分子和分母。
(4)输出:第一行输出有理数的最小堆序列,第二行输出从小到大排序后的序列。
(5)输出的每个有理数必须规约,以n/d的形式输出,其中d>0且gcd(n,d)=0;如果d=1或n=0则直接输出n
(例子)
输入:
5 //有理数个数
3 2 //第1个有理数 3/2
1 3 //第2个有理数 1/3
4 2 //第3个有理数 4/2
12 10 //第4个有理数 12/10
4 6 //第5个有理数 4/6
输出:
1/3 2/3 2 6/5 3/2 //第一行 最小堆
1/3 2/3 6/5 3/2 2 //第二行 排序结果
二、实现过程
1.实现Rational类
Rational类利用gcd()函数(找最大公约数)在初始化的时候对分数化简为最简状态,比较大小的实现则基于将两分数通分后对分子大小的比较。printhelp()函数则实现了按要求输出分数。`
int gcd(int a, int b)
{
if(a % b == 0)
return b;
return gcd(b, a%b);
}
class Rational{
friend bool operator<(const Rational& r1, const Rational& r2)
{ return r1.N * r2.D < r1.D * r2.N;}
friend bool operator<=(const Rational& r1, const Rational& r2)
{ return r1.N * r2.D <= r1.D * r2.N;}
friend bool operator>(const Rational& r1, const Rational& r2)
{ return r1.N * r2.D > r1.D * r2.N;}
friend bool operator>=(const Rational& r1, const Rational& r2)
{ return r1.N * r2.D >= r1.D * r2.N;}
friend bool operator==(const Rational& r1, const Rational& r2)
{ return r1.N * r2.D == r1.D * r2.N;}
friend bool operator!=(const Rational& r1, const Rational& r2)
{ return r1.N * r2.D != r1.D * r2.N;}
public:
int N; //分子
int D; //分母, 要求大于0
Rational() {} //default constructor
Rational(int n){ N=n; D=1;} //constructor for integer value
Rational(int n, int d)
{
if(n==0)
{
N = n;
D = d;
}
else
{
int c;
c = gcd(abs(n),d);
N = n/c;
D = d/c;
}
} //normal constructor
Rational(const Rational& r){N=r.N; D=r.D;} //copy constructor
Rational& operator=(const Rational& r) {N=r.N; D=r.D; return *this;} // assignment override
void printhelp()
{
if(N==0)
cout << 0;
else if(D==1)
cout << N;
else
cout << N << "/" << D;
return;
}
};
2.实现最小堆
基于课本定义实现最小堆,包括shiftdown()、构造函数、isLeaf()(判断是否为叶子结点)、leftchild(),rightchild()(返回左、右孩子)、parent()返回父节点)、insert()(插入元素)、removefirst()(删除第一个元素)、remove()(删除指定位置元素)、printhelp()(输出堆元素)、heapsort()(堆排序)。其中堆的元素类型为泛型,可根据用户需要类型传入参数,具有通用性。
//最小堆的实现
template<typename E>
class heap
{
private:
E * Heap;
int maxsize;
int n;
void shifdown(int pos) //helper to put element at its correct position
{
while(!isLeaf(pos))
{
int j = leftchild(pos);
int rc = rightchild(pos);
if((rc < n) && (Heap[rc]<Heap[j]))
j = rc;
if(Heap[pos]<Heap[j])
return;
swap(Heap,pos,j);
pos = j;
}
}
public:
heap(E *h, int num, int max)
{Heap = h; n = num; maxsize = max; buildHeap();}
int size() const
{return n;}
bool isLeaf(int pos) const
{return (pos>=n/2)&&(pos<n);}
int leftchild(int pos) const
{return 2*pos+1;}
int rightchild(int pos) const
{return 2*pos+2;}
int parent(int pos) const
{return (pos-1)/2;}
void buildHeap()
{
for(int i=n/2-1; i>=0; i--)
shifdown(i);
}
void insert(const E & it)
{
if(n>=maxsize)
{
cout << "Heap is full";
return;
}
int curr = n++;
Heap[curr] = it;
while((curr!=0) && (Heap[curr] < Heap[parent(curr)]))
{
swap(Heap,curr,parent(curr));
curr = parent(curr);
}
}
E removefirst()
{
if(n<=0)
{
cout << "Heap is empty";
return NULL;
}
swap(Heap,0,--n); //Swap the first with last value
if(n!=0)
shifdown(0);
return Heap[n];
}
E remove(int pos)
{
if(pos<0 || pos>=n)
{
cout << "Bad position";
return NULL;
}
if(pos==(n-1))
n--;
else
{
swap(Heap,pos,--n);
while((pos!=0) && (Heap[pos] < Heap[parent(pos)]))
{
swap(Heap,pos,parent(pos));
pos = parent(pos);
}
if(n!=0)
shifdown(pos);
}
return Heap[n];
}
void printheap() { //print Heap
for (int i = 0; i < n; i++) {
Heap[i].printhelp();
cout << " ";
}
return;
}
void heapsort(int n)
{
E maxval;
for(int i=0; i<n; i++)
{
maxval = this->removefirst();
}
return;
}
};
3.补充函数
① Swap函数
可实现不同类型元素的交换操作`
template<typename E>
void swap(E * a, int i, int j)
{
E temp = a[i];
a[i] = a[j];
a[j] = temp;
return;
}
② ``Main()函数
按要求输入数据,并建堆,实现堆排序。
int main()
{
int T;
cin >> T;
Rational compute[10];
for(int i=0; i<T; i++)
{
int son;
int mum;
cin >> son >> mum;
compute[i] = Rational(son,mum);
}
heap<Rational> tryone(compute,T,T);
tryone.printheap();
cout << endl;
tryone.heapsort(T);
for(int i=T-1; i>=0; i--)
{
compute[i].printhelp();
if(i==0)
cout << endl;
else
cout << " ";
}
system("pause");
return 0;
}
`
记得点赞收藏喏