利用最小堆完成有理数的类定义以及有理数逻辑运算

一、要求:

  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等功能
    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;
}

`
记得点赞收藏喏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值