日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++實現關系與關系矩陣的代碼詳解_C 語言

作者:Festu ? 更新時間: 2022-06-07 編程語言

ADT

集合

template    //集合的元素類型
class Set{  //集合ADT
    int size;   //基數
    vector p;
    
    public:
    Set():size(0){}
    Set(int s):size(s){
        p.resize(s);    //重置大小
    }
    int getSize()const{ return size; }
    void push(Type e){  //添加元素
        size++;
        p.push_back(e);
    void set(int pos,Type e){   //設置元素值
        p[pos]=e;
    Type operator[](int i){ return p[i]; }  //下標讀取
    int findElem(Type e){   //返回指定元素的下標
        for(int i=0;i

關系

template
class Relation{
    Set dom;    //定義域
    Set ran;    //值域
    
    public:
    Relation():dom(),ran(){}  //無規模的初始化
    Relation(int r_,int c_):dom(r_),ran(c_){}   //有規模的初始化
    int getR()const { return dom.getSize(); }     //返回行,基類私有成員只可調用基類非私有函數獲得
    int getC()const { return ran.getSize(); }     //返回列
    Set getDom()const { return dom; }     //返回定義域
    Set getRan()const { return ran; }     //返回值域
    void pushDom(Type e){ dom.push(e); }    //給定義域添加元素
    void pushRan(Type e){ ran.push(e); }        //給值域添加元素
    int findDom(Type e){    //尋找定義域中元素的位置
        return dom.findElem(e);
    }
    int findRan(Type e){    //尋找值域中元素的位置
        return ran.findElem(e);
};

關系矩陣

template
class RMatrix:public Relation{
    vector< vector > m;  //二維矩陣用vector實現,注意不能使用bool類型,它有很高的特殊性
    public:
    RMatrix(int r_,int c_):Relation(r_,c_){
        for(int i=0;i v(c_,0);
            m.push_back(v);     //推入r_個長度為c_的vector數組構成一個r*c的二維數組
        }
    }
    RMatrix():Relation(){   //不輸入矩陣大小時
        for(int i=0;i v(MAX_NUM,0);
            m.push_back(v);
        }
    }
    RMatrix(const RMatrix &M){  //復制構造函數
       // printf("here!");
        Set Dom=M.getDom(),Ran=M.getRan();
        int k1=Dom.getSize(),k2=Ran.getSize();
        for(int i=0;i::pushDom(Dom[i]);
        }
        for(int i=0;i::pushRan(Ran[i]);
        }
        m.resize(k1);
        for(int i=0;i::getDom().getSize();  //在子類中調用基類函數需要制定基類
        int col=Relation::getRan().getSize();    
     //   printf("row=%d,col=%d",row,col);
        m.resize(row);
        for(int i=0;i operator[](int p1)const { return m[p1]; }    //可以直接雙括號使用!
    void set(int p1,int p2,short e){     //設置矩陣值
        m[p1][p2]=e;
    }
    void push(vector v){  //添加矩陣的行
        m.push_back(v);
    }
    /* 將兩個關系矩陣合成,括號內的在右 */
    RMatrix matrixSynthesis(const RMatrix &M1)const {
        RMatrix M;    //此處的M是臨時變量,必定被銷毀,無法作為引用被返回	( d=Relation::getDom(),r=M1.getRan();	//矩陣合成的行列關系差點弄錯!
        int k1=d.getSize(),k2=r.getSize(),k3=M1.getR();
        for(int i=0;i::getR(),c=Relation::getC();
        for(int i=0;i::getR();
        for(int i=0;i::getR();
        for(int i=0;i::getR();
        for(int i=0;i::getR();
        for(int i=0;i M_=matrixSynthesis(*this);	//const函數只能調用const函數 ::getR();
        for(int i=0;i
  • ' as 'this' argument discards qualifiers",原因是當時我只將 isPassing 函數設為const,卻沒把其中調用的 matrixSynthesis 函數設為const。

功能實現

關系的矩陣表示

根據關系輸出矩陣:

void inputRelation(RMatrix &M1){    //輸入關系
    printf("請輸入集合A的元素:\n");
    string str;
   // cin.get();  //這里不能直接這樣寫,因為前面有可能是沒有換行符的,那你就會少讀一個字符,所以只能靈活加
    getline(cin,str);
    stringstream ss1(str);
    char inp;
    while(ss1>>inp){
        M1.pushDom(inp);
        M1.pushRan(inp);
    }
    /*
    printf("請輸入集合B的元素:\n");
    stringstream ss2(str);
    while(ss2>>inp){
    int k1=M1.getR(),k2=M1.getC();
    Set A=M1.getDom(),B=M1.getRan();
    */
    M1.updateSize();
    printf("請輸入關系R:(格式為\'a,b\'并用空格分割)\n");
    stringstream ss(str);
    int a,b;
    int isA=1;
    while(ss>>inp){     //使用">>"流輸入字符類型會自動忽略空格...抽象了,printf是讀取空格的
    //    printf("%c",inp);
        if(inp==',')
            isA=0;
        else{
            if(isA)
                a=M1.findDom(inp);
            else{
                b=M1.findRan(inp);
                isA=1;
                M1.set(a,b,1);
            }
                
        }
    printf("\n");
    return;
}
void outputMatrix(const RMatrix &M1){    //格式化輸出矩陣,要定義常量成員函數
    Set Dom=M1.getDom(),Ran=M1.getRan();
    printf("關系矩陣如下:\n");
    for(int i=0;i<=k1;i++){
     //   printf("here?");    //手動斷點
        for(int j=0;j<=k2;j++){
            if(i==0 && j==0) printf("  ");
            else
                if(j==0) printf("%c ",Dom[i-1]);
                else
                    if(i==0) printf("%c ",Ran[j-1]);
                    else{
                        printf("%d ",M1[i-1][j-1]);
                    }
        printf("\n");
int main(){
    RMatrix M1;   //設置集合的元素為字符類型
    inputRelation(M1);
    outputMatrix(M1);
    return 0;

根據矩陣輸出關系序偶:

void inputMatrix(RMatrix &M1){    //輸入矩陣
    printf("請輸入集合A的元素:\n");
    string str;
    getline(cin,str);
    stringstream ss1(str);
    char inp;
    while(ss1>>inp){
        M1.pushDom(inp);
        M1.pushRan(inp);
    }
    /*
    printf("請輸入集合B的元素:\n");
    getline(cin,str);
    stringstream ss2(str);
    while(ss2>>inp){
        M1.pushRan(inp);
    }
    int k1=M1.getR(),k2=M1.getC();
    Set A=M1.getDom(),B=M1.getRan();
    */
    M1.updateSize();
    printf("請輸入關系矩陣:(空格分隔)\n");
    int k=M1.getC(),tmp;
    for(int i=0;i &M1){    //格式化輸出序偶,記得定義常量成員函數
    int k1=M1.getR(),k2=M1.getC();
    Set Dom=M1.getDom(),Ran=M1.getRan();
    printf("關系序偶如下:\n");
    for(int i=0;i",i,j);
                printf("(%c,%c) ",Dom[i],Ran[j]);
            }
        }
        printf("\n");
    }
}
int main(){
    RMatrix M1;   //設置集合的元素為字符類型
    inputMatrix(M1);
    outputRelation(M1);
    return 0;
}

關系的性質判斷

I. 輸入一個包含n個元素的集合A,要求隨機產生3個定義在集合A上的不同的關系R1,R2,R3,其中,R1和R2是自反且對稱的,R3是反對稱的,并顯示R1,R2,R3的關系矩陣表示。

先上一個嘗試用偽隨機實現的算法

void inputSet(RMatrix &M1){    //輸入集合
    printf("請輸入集合A的元素:\n");
    string str;
    getline(cin,str);
    stringstream ss1(str);
    char inp;
    while(ss1>>inp){
        M1.pushDom(inp);
        M1.pushRan(inp);
    }
    /*
    printf("請輸入集合B的元素:\n");
    stringstream ss2(str);
    while(ss2>>inp){
    int k1=M1.getR(),k2=M1.getC();
    Set A=M1.getDom(),B=M1.getRan();
    */
    M1.updateSize();
    printf("\n");
    return;
}
void outputMatrix(const RMatrix &M1){    //格式化輸出矩陣,要定義常量成員函數
    Set Dom=M1.getDom(),Ran=M1.getRan();
    printf("關系矩陣如下:\n");
    for(int i=0;i<=k1;i++){
     //   printf("here?");    //手動斷點
        for(int j=0;j<=k2;j++){
            if(i==0 && j==0) printf("  ");
            else
                if(j==0) printf("%c ",Dom[i-1]);
                else
                    if(i==0) printf("%c ",Ran[j-1]);
                    else{
                        printf("%d ",M1[i-1][j-1]);
                    }
        }
        printf("\n");
void getRandom(RMatrix &M,bool isSelf,bool isSymmetric,bool antiSymmetric){   //后三個參數標記函數性質,分別為自反性,對稱性,反對稱性
    while(1){
        M.randomRelation();
        if(M.isSelf()==isSelf && M.isSymmetric()==isSymmetric && M.antiSymmetric()==antiSymmetric) return;
int main(){
    RMatrix M1;   //設置集合的元素為字符類型
    inputSet(M1);
    RMatrix M2(M1),M3(M1);
    getRandom(M1,1,1,0);
    getRandom(M2,1,1,0);
    getRandom(M3,0,0,1);
    outputMatrix(M1);
    outputMatrix(M2);
    outputMatrix(M3);
    return 0;

構想是挺美好的,但是偽隨機的效果讓這個方法行不通,因為隨機的效率太低,是按秒變化的,除非直接寫在成員函數中根據一個seed一直隨機,否則程序不可能通暢,但寫在成員函數也不好,太特殊。

以下是后手加工版本:

void inputSet(RMatrix &M1){    //輸入集合
    printf("請輸入集合A的元素:\n");
    string str;
    getline(cin,str);
    stringstream ss1(str);
    char inp;
    while(ss1>>inp){
        M1.pushDom(inp);
        M1.pushRan(inp);
    }
    /*
    printf("請輸入集合B的元素:\n");
    getline(cin,str);
    stringstream ss2(str);
    while(ss2>>inp){
        M1.pushRan(inp);
    }
    int k1=M1.getR(),k2=M1.getC();
    Set A=M1.getDom(),B=M1.getRan();
    */
    M1.updateSize();
    printf("\n");
    return;
}
void outputMatrix(const RMatrix &M1,string str=""){    //格式化輸出矩陣,要定義常量成員函數
    int k1=M1.getR(),k2=M1.getC();
    Set Dom=M1.getDom(),Ran=M1.getRan();
    str=str+"關系矩陣如下:\n";     //連接矩陣名稱
    printf("%s",str.c_str());
    for(int i=0;i<=k1;i++){
     //   printf("here?");    //手動斷點
        for(int j=0;j<=k2;j++){
            if(i==0 && j==0) printf("  ");
            else
                if(j==0) printf("%c ",Dom[i-1]);
                else
                    if(i==0) printf("%c ",Ran[j-1]);
                    else{
                        printf("%d ",M1[i-1][j-1]);
                    }
        }
        printf("\n");
    }
}
void getRandom(RMatrix &M,bool isSelf,bool isSymmetric,bool antiSymmetric){   //后三個參數標記函數性質,分別為自反性,對稱性,反對稱性
    M.randomRelation();     //先基礎隨機化處理
    int r=M.getC();
    if(isSelf){     //補足自反性
        if(!M.isSelf()){
            for(int i=0;i M1;   //設置集合的元素為字符類型
    inputSet(M1);
    RMatrix M2(M1),M3(M1);
    getRandom(M1,1,1,0);
    getRandom(M2,1,1,0);
    getRandom(M3,0,0,1);
    outputMatrix(M1,"R1");
    outputMatrix(M2,"R2");
    outputMatrix(M3,"R3");
    return 0;
}

輸出函數優化了一下,可以輸出矩陣名稱了。

II.給定一個矩陣判斷其性質,并輸出結果

void inputMatrix(RMatrix &M1){    //輸入矩陣
    for(int i=0;i<6;i++){
        M1.setDom(i,' ');
        M1.setRan(i,' ');
    }
    printf("請輸入關系矩陣:(空格分隔)\n");
    int k=6,tmp;
    for(int i=0;i &M1){
    if(M1.isSelf()) printf("具有自反性\n");
    if(M1.isSymmetric()) printf("具有對稱性\n");
    if(M1.antiSymmetric()) printf("具有反對稱性\n");
    if(M1.isPassing()) printf("具有傳遞性\n");
}
int main(){
    RMatrix M1(6,6);
    inputMatrix(M1);
    judgeMatrix(M1);
    return 0;
}

關系的合成

關系合成運算:

void outputMatrix(const RMatrix &M1){    //格式化輸出矩陣,要定義常量成員函數
    int k1=M1.getR(),k2=M1.getC();
    Set Dom=M1.getDom(),Ran=M1.getRan();
    printf("關系矩陣如下:\n");
    for(int i=0;i<=k1;i++){
     //   printf("here?");    //手動斷點
        for(int j=0;j<=k2;j++){
            if(i==0 && j==0) printf("  ");
            else
                if(j==0) printf("%c ",Dom[i-1]);
                else
                    if(i==0) printf("%c ",Ran[j-1]);
                    else{
                        printf("%d ",M1[i-1][j-1]);
                    }
        }
        printf("\n");
    }
}
void inputRelation(RMatrix &M1,RMatrix &M2){    //輸入關系
    printf("請輸入集合A的元素:\n");
    string str;
    getline(cin,str);
    stringstream ss1(str);
    char inp;
    while(ss1>>inp){
        M1.pushDom(inp);
    }
    printf("請輸入集合B的元素:\n");
    getline(cin,str);
    stringstream ss2(str);
    while(ss2>>inp){
        M1.pushRan(inp);
        M2.pushDom(inp);
    }
    printf("請輸入集合C的元素:\n");
    getline(cin,str);
    stringstream ss3(str);
    while(ss3>>inp){
        M2.pushRan(inp);
    }
    M1.updateSize();
    M2.updateSize();
    
    printf("請輸入關系R1:(格式為\'a,b\'并用空格分割)\n");
    getline(cin,str);
    stringstream ss(str);
    int a,b;
    int isA=1;
    while(ss>>inp){     //使用">>"流輸入字符類型會自動忽略空格...抽象了,printf是讀取空格的
    //    printf("%c",inp);
        if(inp==',')
            isA=0;
        else{
            if(isA)
                a=M1.findDom(inp);
            else{
                b=M1.findRan(inp);
                isA=1;
                M1.set(a,b,1);
            }
                
        }
    }
    printf("R1");
    outputMatrix(M1);
    printf("請輸入關系R2:(格式為\'a,b\'并用空格分割)\n");
    getline(cin,str);
    stringstream ss_(str);
    isA=1;
    while(ss_>>inp){     //使用">>"流輸入字符類型會自動忽略空格...抽象了,printf是讀取空格的
    //    printf("%c",inp);
        if(inp==',')
            isA=0;
        else{
            if(isA)
                a=M2.findDom(inp);
            else{
                b=M2.findRan(inp);
                isA=1;
                M2.set(a,b,1);
            }
                
        }
    }
    printf("R2");
    outputMatrix(M2);
    printf("\n");
    return;
}
RMatrix multiplyMatrix(const RMatrix &M1,const RMatrix &M2){  //默認集合元素就是char類型~
    RMatrix M;
        Set d=M1.getDom(),r=M2.getRan();
        int k1=d.getSize(),k2=r.getSize(),k3=M2.getR();
        for(int i=0;i &M1){    //格式化輸出序偶,記得定義常量成員函數
    int k1=M1.getR(),k2=M1.getC();
    Set Dom=M1.getDom(),Ran=M1.getRan();
    printf("關系序偶如下:\n");
    for(int i=0;i",i,j);
                printf("(%c,%c) ",Dom[i],Ran[j]);
            }
        }
        printf("\n");
    }
}
void getCalculate(const RMatrix &M1,const RMatrix &M2){
    RMatrix M=M1.matrixSynthesis(M2);     //布爾積運算
    printf("布爾積運算所得的");
    outputMatrix(M);    //輸出布爾積結果
    RMatrix M_=multiplyMatrix(M1,M2);     //矩陣乘積運算
    printf("矩陣乘積所得的");
    outputMatrix(M_);
    outputRelation(M);
    return;
}
int main(){
    RMatrix M1,M2;   //設置集合的元素為字符類型
    inputRelation(M1,M2);
    getCalculate(M1,M2);
    return 0;
}

縫合并優化了幾個函數。

關系的n次運算:

void outputMatrix(const RMatrix &M1){    //格式化輸出矩陣,要定義常量成員函數
    int k1=M1.getR(),k2=M1.getC();
    Set Dom=M1.getDom(),Ran=M1.getRan();
    printf("關系矩陣如下:\n");
    for(int i=0;i<=k1;i++){
     //   printf("here?");    //手動斷點
        for(int j=0;j<=k2;j++){
            if(i==0 && j==0) printf("  ");
            else
                if(j==0) printf("%c ",Dom[i-1]);
                else
                    if(i==0) printf("%c ",Ran[j-1]);
                    else{
                        printf("%d ",M1[i-1][j-1]);
                    }
        }
        printf("\n");
    }
}
void inputRelation(RMatrix &M1){    //輸入關系
    printf("請輸入集合A的元素:\n");
    string str;
   // cin.get();  //這里不能直接這樣寫,因為前面有可能是沒有換行符的,那你就會少讀一個字符,所以只能靈活加
    getline(cin,str);
    stringstream ss1(str);
    char inp;
    while(ss1>>inp){
        M1.pushDom(inp);
        M1.pushRan(inp);
    }
    M1.updateSize();
    printf("請輸入關系R:(格式為\'a,b\'并用空格分割)\n");
    getline(cin,str);
    stringstream ss(str);
    int a,b;
    int isA=1;
    while(ss>>inp){     //使用">>"流輸入字符類型會自動忽略空格...抽象了,printf是讀取空格的
    //    printf("%c",inp);
        if(inp==',')
            isA=0;
        else{
            if(isA)
                a=M1.findDom(inp);
            else{
                b=M1.findRan(inp);
                isA=1;
                M1.set(a,b,1);
            }
                
        }
    }
    printf("已知R");
    outputMatrix(M1);
    return;
}
void nR(const RMatrix &M1,int n){
    RMatrix M(M1);
    int n_=n;
    n--;
    while(n--)
        M=M.matrixSynthesis(M);
    printf("得出 R^%d",n_);
    outputMatrix(M);
    return;
}
int main(){
    RMatrix M1;   //設置集合的元素為字符類型
    inputRelation(M1);
    int n;
    printf("請輸入n:");
    scanf("%d",&n);
    nR(M1,n);
    return 0;
}

參考:

知乎-vector

新世紀debug戰士-C++實現偽隨機

原文鏈接:https://www.cnblogs.com/Forest-set-you/p/16098277.html

欄目分類
最近更新