【数据结构】NOJ013—以十字链表为存储结构实现矩阵相加

这篇博客主要介绍了如何使用十字链表数据结构来创建矩阵,并实现两个矩阵的相加。首先,定义了十字链表节点结构,包括行号、列号、值和指向下方及右方的指针。接着,详细描述了如何根据行数和列数建立十字链表,以及如何插入节点。在矩阵相加的过程中,遍历两个十字链表,将元素按位置插入并累加值。最后,给出了完整的C语言代码实现,包括创建、插入和打印矩阵等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

解析:

首先是十字链表的建立。十字列表节点包括行号、列号、值、和指向下方和右方的两个指针。然后定义一个十字链表,根据行数m和列数n申请m个行头地址指针rheadn个列头地址指针chead

typedef struct Node{//定义十字链表结点
    int i,j;
    int val;
    struct Node *right,*down;
}Node,*Link;

typedef struct{//定义十字链表
    Link *rhead,*chead;//定义行和列的头指针地址组
    int mu,nu,tu;
}CrossList;

每输入一个节点,检查它所在的行号,其所在行的行头指针为不为空,为空直接连在行头指针后面不为空就遍历该行的链表,把此节点插入进去。其次检查列号,同理,选择直接连在列头指针后面还是直接插入进去。这样就建立好了十字链表。

建立好两个十字链表之后,同时遍历两个十字链表,根据行号和列号和值得到新的十字链表。

遍历所有的行头指针,如果本行为空说明本行没有链表,直接跳入下一行。如果不为空,说明本行有。遍历改行的链表,得到行号和列号进行比较。不同的话按先后顺序插入,相同的话值相加插入。

重点:

(1)重点是十字链表的建立

(2)注意遍历十字链表

代码:

#include<stdio.h>
#include<stdlib.h>

typedef struct OLNode{//定义十字链表结点
    int i,j;
    int val;
    struct OLNode *right,*down;
}OLNode,*OLink;

typedef struct{//定义十字链表
    OLink *rhead,*chead;//定义行和列的头指针地址组
    int mu,nu,tu;
}CrossList;

void CreatMatrix_OL(CrossList *M, int m, int n, int t){//创建一个m行n列容量为t的十字链表
    //初始化M头节点,行、列和容量信息,开辟行列链表头节点空间
    M->rhead = M->chead = NULL;
    M->mu = m;
    M->nu = n;
    M->tu = t;
    M->rhead = (OLink*)malloc(sizeof(OLink)*(m+1));
    M->chead = (OLink*)malloc(sizeof(OLink)*(n+1));
    //初始化行列链表头节点
    for(int k=1;k<=m;k++){
        M->rhead[k] = NULL;
    }
    for(int k=1;k<=n;k++){
        M->chead[k] = NULL;
    }
    //存储接收的数据
    int i,j,v;
    for(int k=0;k<t;k++){
        int i,j,v;
        OLink p,q;
        scanf("%d %d %d",&i,&j,&v);
        //新建节点储存输入数据,并将其接入十字链表中
        p = (OLink)malloc(sizeof(OLNode));
        p->i = i;
        p->j = j;
        p->val = v;
        //如果数据所在行的头指针为空,或头指针的列大于数据的列,则数据位置即为头指针
        if(M->rhead[i]==NULL || M->rhead[i]->j>j){
            M->rhead[i] = p;
        }
        else{//否则依次查找该元素插入位置
            for(q=M->rhead[i];(q->right)&&(q->right->j<j);q=q->right);
            p->right = q->right;
            q->right = p;
        }
        p->down = NULL;
        //列的操作同行的类似
        if(M->chead[j]==NULL || M->chead[j]->i>i){
            M->chead[j] = p;
        }
        else{
            for(q=M->chead[j];(q->down)&&(q->down->i<i);q=q->down);
            p->down = q->down;
            q->down = p;
        }
        p->right = NULL;
    }
}

void Insert(CrossList *M, OLink p){//插入节点
    int i=p->i,j=p->j;
    if(M->rhead[i]==NULL){//如果该行为空
        M->rhead[i] = p;
        M->tu++;
    }
    else{
        OLink q=M->rhead[i];
        OLink pre = q;//当且仅当插入位置即头节点时有pre=q
        while(q&&(q->j<p->j)){//寻找插入位置
            pre = q;
            q = q->right;
        }
        if(q&&(q->j==p->j)){//如果插入位置有元素
            q->val += p->val;
            if(q->val==0){
                if(pre==q){
                    M->rhead[i] = q->right;
                }
                else{
                    pre->right = q->right;
                }
                M->tu--;
            }
        }
        else{//插入位置无元素
            if(pre==q){
                    M->rhead[i] = p;
                    p->right = q;
                }
                else{
                    pre->right = p;
                    p->right =q;
                }
                M->tu++;
        }
    }
    if(M->chead[j]==NULL){//列操作与行操作类似
        M->chead[j] = p;
    }
    else{
        OLink q=M->chead[j];
        OLink pre = q;//当且仅当插入位置即头节点时有pre=q
        while(q&&(q->i<p->i)){//寻找插入位置
            pre = q;
            q = q->down;
        }
    }
}

void AddElem(CrossList *M, CrossList *N){//将矩阵M加到矩阵N上
   OLink p,q;
   p = (OLink)malloc(sizeof(OLNode));
   for(int k=1;k<=N->mu;k++){
        p = N->rhead[k];
        while(p){//依次找出N中每个元素插入M中
            q = (OLink)malloc(sizeof(OLNode));//不能将p直接插入,会打乱N,应另设一个元素保存数据
            q->down = p->down;
            q->right = q->right;
            q->val = p->val;
            q->i = p->i;
            q->j = p->j;
            Insert(M,q);
            p = p->right;
        }
    }
}

void PrintMatrix_OL(CrossList *M){//按照先行后列依次输出
    for(int i=1;i<=M->mu;i++){
        OLink p=M->rhead[i];
        for(int j=1;j<=M->nu;j++){
            if(p&&j==p->j){
                printf("%d %d %d\n",p->i,p->j,p->val);
                p=p->right;
            }
        }
    }
}

int main(){
    int m,n,t1,t2;
    scanf("%d %d %d %d",&m,&n,&t1,&t2);
    CrossList *M,*N;
    M = (CrossList*)malloc(sizeof(CrossList));
    N = (CrossList*)malloc(sizeof(CrossList));
    CreatMatrix_OL(M,m,n,t1);
    CreatMatrix_OL(N,m,n,t2);
    AddElem(M,N);
    PrintMatrix_OL(M);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值