手捏脚盆鸡,敲打棒子国。单脚踩蛙蛙,踏平大漂亮。

导航

稀疏矩阵-正交链表-加法

两个以正交链表表示的稀疏矩阵的加法算法:

//自己写的亲测有效,经过严格测试:
#include<stdio.h>
#include<stdlib.h>
#define MaxSize  100
typedef   enum { H, E }   TagField;
typedef struct term {
    int row, col, value;
}Term;
typedef struct mnode {
    struct mnode* Right, * Down;
    TagField Tag;
    union {
        struct mnode* Next;
        Term Element;
    }U;
}MNode;
typedef struct linkedmatrix {
    MNode* Head;
    MNode* HD[MaxSize];
}LinkedMatrix;
MNode* NewNode() {
    MNode* temp = (MNode*)malloc(sizeof(MNode));
    temp->Down = NULL;
    temp->Right = NULL;
    return temp;
}
//该算法的时间复杂度为O(heads+nozeros)
LinkedMatrix  MRead(void) {
    int rows, cols, nozeros, heads;
    int row, col, value, i;
    MNode* ptemp, * prow_last, *pcol_last, * pnode, * Temp;
    LinkedMatrix A;
    printf("Enter the number of rows, columns  and number of nozero terms:  ");
    scanf_s("%d%d%d", &rows, &cols, &nozeros);
    //建立正交链表的表头结点
    heads = (cols > rows) ? cols : rows;
    pnode = NewNode();
    pnode->Tag = E;
    pnode->U.Element.row = rows;
    pnode->U.Element.col = cols;
    pnode->U.Element.value = nozeros;
    pnode->Down = NULL;
    A.Head = pnode;
    Temp = A.Head; //把A的表头结点赋给一个临时变量
    if (!heads) {
        pnode->Right=pnode;
    }
    else {
        //建立heads 个行/列表头结点, 形成一个包含有Heads个元素的包含有表头节点的空循环链表,
        for (i = 0; i < heads; i++) {
            A.HD[i] = NewNode();
            A.HD[i]->Tag = H;
            A.HD[i]->Right = A.HD[i];
            A.HD[i]->Down = A.HD[i];
            if (i==0) {
                Temp->Right = A.HD[i];
            }
            else {
                Temp->U.Next = A.HD[i];
            }
            Temp = A.HD[i];
        }
        Temp->U.Next = A.Head;
        //包含有Heads个元素的包含有表头节点的空循环链表创建完成
        //从第0行起,按行插入非0元素
        for (i = 0; i < nozeros;i++) {
            printf("Enter row , col   and  value: ");
            scanf_s("%d%d%d", &row, &col, &value);
            ptemp = NewNode();
            ptemp->Tag = E;
            ptemp->U.Element.row = row;
            ptemp->U.Element.col = col;
            ptemp->U.Element.value = value;
            ptemp->Right = A.HD[row];
            ptemp->Down = A.HD[col];

            prow_last = A.HD[row];
            for (; prow_last->Right != A.HD[row]; prow_last = prow_last->Right);
            prow_last->Right = ptemp;
            prow_last = ptemp;

            pcol_last=A.HD[col];
            for (; pcol_last->Down != A.HD[col]; pcol_last = pcol_last->Down);
            pcol_last->Down=ptemp;
            pcol_last=ptemp;
        }

    }
    return A;
}
LinkedMatrix Add2LinkedMatrix(LinkedMatrix a, LinkedMatrix b) {
    MNode* p_head_temp, * prow_temp, *p_a_row_temp, * p_a_col_temp, * ptemp, * p_a_row_temp1;
    int equalFlag = 0, lastrowFlag=0,lastcolFlag=0;
    LinkedMatrix result;
    if (a.Head==NULL ||  b.Head==NULL) {
        printf("can not be null\n");
        return;
    }
    if (a.Head->U.Element.row != a.Head->U.Element.row || a.Head->U.Element.col != a.Head->U.Element.col) {
        printf("the shape of two Matrix must be itentical\n");
        return;
    }
    p_head_temp = b.Head->Right;
    for (; p_head_temp != b.Head; p_head_temp = p_head_temp->U.Next) {
        prow_temp = p_head_temp->Right;//b中新的一行
        for (; prow_temp != p_head_temp; prow_temp = prow_temp->Right) {//prow_temp按行扫描b,prow_temp指代当前b矩阵中非零结点
            //printf("%d    %d    %d\n", prow_temp->U.Element.row, prow_temp->U.Element.col, prow_temp->U.Element.value);
            //在这里开始逐一将b中的元素与a中的元素进行对比。如果相同位置中,a有b的同样的元素,就直接将值相加。如果没有,就将b中的元素插入到a的这个位置上。
            equalFlag = 0;
            p_a_row_temp = a.HD[prow_temp->U.Element.row];
            for (; p_a_row_temp->Right != a.HD[prow_temp->U.Element.row]; p_a_row_temp = p_a_row_temp->Right) {
                if (p_a_row_temp->U.Element.row  == prow_temp->U.Element.row && p_a_row_temp->U.Element.col == prow_temp->U.Element.col) {//如果找到了这个元素, 行列一样的话
                    p_a_row_temp->U.Element.value += prow_temp->U.Element.value;
                    equalFlag = 1;
                    break;
                }
            }
            if (equalFlag ==0 && p_a_row_temp->U.Element.row == prow_temp->U.Element.row && p_a_row_temp->U.Element.col == prow_temp->U.Element.col) {//如果找到了这个元素, 行列一样的话
                p_a_row_temp->U.Element.value += prow_temp->U.Element.value;
                continue;
            }
            if (equalFlag==0) {//如果这个元素a中没有的话,那就将此元素插入到a中
                lastrowFlag = 0;
                lastcolFlag = 0;
                a.Head->U.Element.value++;
                ptemp = NewNode();
                ptemp->Tag = E;
                ptemp->U.Element.row = prow_temp->U.Element.row;
                ptemp->U.Element.col = prow_temp->U.Element.col;
                ptemp->U.Element.value = prow_temp->U.Element.value;
                ptemp->Right = NULL;
                ptemp->Down = NULL;
                //先把行搞定
                p_a_row_temp1 = a.HD[prow_temp->U.Element.row];  //刷新 p_a_row_temp 为 a的行表头
                for (; p_a_row_temp1->Right != a.HD[prow_temp->U.Element.row]; p_a_row_temp1 = p_a_row_temp1->Right) {
                    if (p_a_row_temp1->Right->U.Element.col > ptemp->U.Element.col) {
                        ptemp->Right = p_a_row_temp1->Right;
                        p_a_row_temp1->Right=ptemp;
                        lastrowFlag = 1;
                        break;
                    }
                }
                if (lastrowFlag==0) {
                    ptemp->Right=    a.HD[prow_temp->U.Element.row];
                    p_a_row_temp1->Right = ptemp;  // 这时 p_a_row_temp1 指代 a中当前行的最后一个结点
                }
                //再把列搞定
                p_a_col_temp = a.HD[prow_temp->U.Element.col];
                for (; p_a_col_temp->Down != a.HD[prow_temp->U.Element.col]; p_a_col_temp = p_a_col_temp->Down) {
                    if (p_a_col_temp->Down->U.Element.row > ptemp->U.Element.row) {
                        ptemp->Down = p_a_col_temp->Down;
                        p_a_col_temp->Down = ptemp;
                        lastcolFlag = 1;
                        break;
                    }
                }
                if (lastcolFlag == 0) {
                    ptemp->Down = a.HD[prow_temp->U.Element.col];
                    p_a_col_temp->Down = ptemp;  // 这时 p_a_row_temp1 指代 a中当前行的最后一个结点
                }
            }
        }
    }
    result = a;
    return result;
}
void PrintLinkedMatrix(LinkedMatrix A) {
    MNode* ptemp, * prow_temp;
    ptemp = A.Head->Right;
    for (; ptemp != A.Head; ptemp= ptemp->U.Next) {
        prow_temp = ptemp->Right;
        for (; prow_temp != ptemp; prow_temp = prow_temp->Right) {
            printf("%d    %d    %d\n", prow_temp->U.Element.row, prow_temp->U.Element.col, prow_temp->U.Element.value);
        }
    }
}
void main() {
    LinkedMatrix A, B,addRes;
    A = MRead();
    PrintLinkedMatrix(A);
    printf("**********************\n");
    B = MRead();
    PrintLinkedMatrix(B);
    printf("**********************\n");
    addRes = Add2LinkedMatrix(A, B);
    PrintLinkedMatrix(addRes);
    system("pause");
}

UP主是一名程序员,再次考研复习中,需要讨论问题一起复习的请联系我。

posted on 2021-11-24 22:09  单手搓木亥弓单  阅读(59)  评论(0编辑  收藏  举报