有理数的堆排序

实验目的:

  1. 掌握最小堆的基本概念,堆的基本运算以及堆排序的流程
  2. 掌握有理数类的定义及逻辑运算规则

实验内容:

  1. 完成有理数的类定义以及有理数逻辑运算函数
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

}
  1. 创建有理数的最小堆,实现siftdown, siftup, insert等功能
  2. 实现基于最小堆的堆排序,按从小到大的顺序输出有理数
  3. 为在线测评系统检测程序的运行,对程序文档及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;
}

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值