实验目的:
- 掌握最小堆的基本概念,堆的基本运算以及堆排序的流程
- 掌握有理数类的定义及逻辑运算规则
实验内容:
- 完成有理数的类定义以及有理数逻辑运算函数
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等功能
- 实现基于最小堆的堆排序,按从小到大的顺序输出有理数
- 为在线测评系统检测程序的运行,对程序文档及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
4 2
12 10
4 6
输出样例:
1/3 2/3 2 6/5 3/2
1/3 2/3 6/5 3/2 2
代码实现:
#include <iostream>
using namespace std;
//堆:1.是一颗完全二叉树 2.堆中存储的数据是局部有序的
//最小堆:任何一个结点存储的值都小于或等于其任意一个子节点存储的值
//求最大公约数,辅助有理数类化简
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) { //normal constructor
if (n == 0) { N = n; D = d; }
else {
int c;
if (n > 0) c = gcd(n, d);
else if (n < 0) c = gcd(-n, d);
N = n / c; D = d / c;
}
}
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;
}
};
//重写swap函数
void swap(Rational* A, int i, int j) {
Rational tem = A[i];
A[i] = A[j];
A[j] = tem;
return;
}
//有理数的最小堆实现
class heap {
private:
Rational* Heap; //Pointer to the heap array
int maxsize; //Maximum size of the heap
int n; //Number of elements now in the heap
//Helper function to put element in its correct place
void siftdown(int pos) {
while (!isLeaf(pos)) {
int j = leftchild(pos);
int rc = rightchild(pos);
if ((rc < n) && (Heap[rc] < Heap[j]))
j = rc; //Set j to smaller child's value
if (Heap[pos] < Heap[j]) return; //pos比j更小,也就到了对的位置
swap(Heap, pos, j); //pos比j大,交换位置
pos = j;
}
return;
}
void siftup(int curr) {
while ((curr != 0) && (Heap[curr] < Heap[parent(curr)])) {
swap(Heap, curr, parent(curr));
curr = parent(curr);
}
return;
}
public:
heap(Rational* h, int num, int max) //Constructor
{
Heap = h; n = num; maxsize = max; buildHeap();
}
int size() const { return n; } //Return current heap size
bool isLeaf(int pos) const //True if pos is a leaf
{
return (pos >= n / 2) && (pos < n);
}
int leftchild(int pos) const
{
return 2 * pos + 1;
} //Return leftchild position
int rightchild(int pos) const
{
return 2 * pos + 2;
} //Return rightchild position
int parent(int pos) const
{
return (pos - 1) / 2;
} //Return parent position
void buildHeap() //Heapify content of heap
{
for (int i = n / 2 - 1; i >= 0; i--) siftdown(i);
}
void printheap() { //print Heap
for (int i = 0; i < n; i++) {
Heap[i].printhelp();
cout << " ";
}
return;
}
//Insert "it" into the heap
void insert(const Rational& it) {
if (n >= maxsize) { cout << "Heap is full" << endl; return; }
int curr = n++;
Heap[curr] = it; //Start at end of heap
//Now sift up until curr's parent < curr
siftup(curr);
return;
}
//Remove first value
Rational removefirst() {
if (n <= 0) { cout << "Heap is empty" << endl; return NULL; }
swap(Heap, 0, --n);
if (n != 0) siftdown(0);
return Heap[n]; //Return deleted value
}
//Remove and return element at specified position
Rational remove(int pos) {
if ((pos < 0) && (pos >= n)) { cout << "Bad position" << endl; return NULL; }
if (pos == (n - 1)) n--; //Last element, no work to do
else {
swap(Heap, pos, --n); //Swap with last value
siftup(pos);
if (n != 0) siftdown(pos);
}
return Heap[n]; //Return deleted value
}
};
//堆排序代码实现
void heapsort(heap H, int n) {
Rational maxval;
for (int i = 0; i < n; i++) //Now sort
maxval = H.removefirst(); //Place maxval at end
return;
}
//主函数
int main() {
int n = 0;
//读入数据
cin >> n;
Rational A[10];
for (int i = 0; i < n; i++) {
int n1, d1;
cin >> n1 >> d1;
A[i] = Rational(n1, d1);
}
//建立最小堆
heap a(A, n, n);
a.printheap();
cout << endl;
//最小堆排序
heapsort(a, n);
for (int i = n-1; i >= 0; i--) {
A[i].printhelp();
if(i==0)
cout << endl;
else cout << " ";
}
return 0;
}
版权声明:本文为qq_45709520原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。