[数据结构] 严蔚敏 矩阵的十字链表存储方法

直接上代码。

最关键的是每次创建新结点之后插入十字链表的算法,也就是分析新结点指针指向的位置,这部分在最后InserttoChainTable函数里。虽然各种变量命名很奇怪,但是能标注的都尽量标注全了。

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

int main()
{
    printf("验证十字链表矩阵的函数\n");
    CrossList M,N;
    {
        FILE *fp = fopen("TestData.txt","r");
//        if (!fp)
//            exit (-1);
        printf("从文件中创建两个矩阵\n");
        CreateSMatrix_OL(fp,2,&M,&N);
        fclose(fp);
        printf("M = \n");
        PrintSMatrix_OL(M);
        printf("N = \n");
        PrintSMatrix_OL(N);
        printf("\n");
    }

    {
        CrossList Tmp;
        printf("将M拷贝到Tmp\n");
        CopySMatrix_OL(&Tmp,M);
        printf("Tmp = \n");
        PrintSMatrix_OL(Tmp);
        printf("\n");
    }
    {
        CrossList T;
        printf("T = M + N = \n");
        AddSMatrix_OL(&T,M,N);
        PrintSMatrix_OL(T);
        printf("\n");
        printf("T = M - N = \n");
        SubSMatrix_OL(&T,M,N);
        PrintSMatrix_OL(T);
        printf("\n");
    }
    {
        CrossList T;
        printf("T = M * N = \n");
        MultSMatrix_OL(&T,M,N);
        PrintSMatrix_OL(T);
        printf("\n");
    }
    {
        CrossList T;
        printf("T = M(T) = \n");
        TransposeSMatrix_OL(&T,M);
        PrintSMatrix_OL(T);
        printf("\n");
    }
    {
        printf("销毁M,N\n");
        DestroySMatrix_OL(&M);
        DestroySMatrix_OL(&N);
        !M.mu && !M.nu && !M.tu && !N.mu && !N.tu && !N.nu? printf("M和N不存在\n"):printf("M和N存在\n");
        printf("\n");
    }
    return 0;
}

 

/**********************************
 *                                *
 * 文件夹: ▲01 绪论              *
 *                                *
 * 文件名: Status.h               *
 *                                *
 * 内  容: 相关状态码及宏函数列表 *
 *                                *
 **********************************/ 

#ifndef STATUS_H
#define STATUS_H

/* 状态码 */
#define	TRUE		1			//真 
#define	FALSE		0			//假
#define YES			1			//是
#define NO          0			//否 
#define	OK			1			//通过
#define	ERROR		0			//错误
#define SUCCESS		1			//成功 
#define UNSUCCESS	0			//失败 
#define	INFEASIBLE	-1			//不可行

#ifndef _MATH_H_ 				//系统中已有此状态码定义,要避免冲突 
#define	OVERFLOW	-2			//堆栈上溢
#define UNDERFLOW	-3			//堆栈下溢
#endif 

#ifndef NULL
#define NULL ((void*)0)
#endif

/* 状态码识别类型 */
typedef int Status;

/*宏函数*/
//函数暂停一段时间
#define Wait(x)\
 {\
	double _Loop_Num_;\
	for(_Loop_Num_=0.01; _Loop_Num_<=100000.0*x; _Loop_Num_+=0.01)\
		;\
 }//设立一个空循环 

//摁Enter键继续 
#define PressEnter\
 {\
	fflush(stdin);\
	printf("Press Enter...");\
	getchar();\
	fflush(stdin);\
 }

#endif
#ifndef CROSSLIST_H
#define CROSSLIST_H

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

#include "Status.h"
#include "Scanf.h"

//十字链表类型定义
typedef int CElemType;

typedef struct OLNode
{
    int i,j;
    CElemType e;
    struct OLNode *right;
    struct OLNode *down;
} OLNode,*OLink;

typedef struct
{
    OLink *rhead; //行链表头指针
    OLink *chead; //列链表头指针
    int mu,nu,tu;
} CrossList;

//函数表
Status CreateSMatrix_OL (FILE *fp,int n,...);

void DestroySMatrix_OL (CrossList *T);

void PrintSMatrix_OL (CrossList T);

void CopySMatrix_OL (CrossList *T, CrossList M);

Status AddSMatrix_OL (CrossList *T,CrossList M, CrossList N);

Status SubSMatrix_OL (CrossList *T, CrossList M, CrossList N);

Status MultSMatrix_OL (CrossList *T, CrossList M,CrossList N);

void TransposeSMatrix_OL (CrossList *T, CrossList M);

Status InserttoChainTable (OLink p, OLink *tmp, OLink tmpcol, CrossList *T);

Status InitMatrixandChain (CrossList *T);
#endif // CROSSLIST_H
#ifndef CROSSLIST_C
#define CROSSLIST_C

#include "CrossList.h"

十字链表类型定义
//typedef int CElemType;
//typedef struct OLNode
//{
//    int i,j;
//    CElemType e;
//    struct OLNode *right;
//    struct OLNode *down;
//} OLNode,*OLink;
//typedef struct
//{
//    OLink *rhead; //行链表头指针
//    OLink *chead; //列链表头指针
//    int mu,nu,tu;
//} CrossList;

//函数表
Status CreateSMatrix_OL (FILE *fp,int n,...)
{
    if (n<1)
        return ERROR;

    int count; //用来计算输入的矩阵个数
    int k; //临时使用的变量
    int number; //扫描时临时使用的变量
    char *tmps;
    OLink p; //用来代表新加入的结点
    OLink q; //用来遍历每行的链表进而与p比较
    CrossList *M; //指向输入的矩阵
    va_list ap;
    va_start (ap,n);
    for (count=1;count<=n;count++){
        M = va_arg(ap,CrossList *);

        tmps = (char *)malloc(5*sizeof(char));
        for (k=0;k<3;k++){
            fscanf(fp,"%s %d",tmps,&number);
            if (strcmpi(tmps,"row:")==0)
                M->mu = number;
            else if (strcmpi(tmps,"col:")==0)
                M->nu = number;
            else if (strcmpi(tmps,"num:")==0)
                M->tu = number;
        }

        fscanf(fp,"%s",tmps);
        if (strcmpi(tmps,"data:")==0){
            //为chead,rhead动态申请空间,注意数组0号不放指针
           InitMatrixandChain (M);

            for (k=1;k<=M->tu;k++){
                p = (OLink) malloc (sizeof(OLNode));
                if (!p)
                    exit (OVERFLOW);

                if (k==1){
                    fscanf(fp," (%d,%d,%d)",&(p->i),&(p->j),&(p->e));
//                     printf("(%d,%d,%d)",(p->i),(p->j),(p->e));
                } else{
                    fscanf(fp,",(%d,%d,%d)",&(p->i),&(p->j),&(p->e));
//                    printf(",(%d,%d,%d)",(p->i),(p->j),(p->e));
                }
//                printf("%d%d%d",p->i,p->j,p->e);
                p->right = p->down = NULL;
                //定位插入行的哪个位置
                if (M->rhead[p->i]==NULL || M->rhead[p->i]->j>p->j){
                    //如果需要插入链表第一位则
                    p->right = M->rhead[p->i];
                    M->rhead[p->i] = p;
                } else {
                    //需要确保比较j的时候q所在结点一定是存在的,更加严谨
                    for (q = M->rhead[p->i];(q->right) && (q->right->j<p->j);q = q->right){}
                    //q指向应当插入的前一位Node;另外防止第一位重复
                    if (q->j==p->j || (q->right) && (q->right->j==p->j)){
                        printf("Repeated position.\n");
                        return ERROR;
                    }
                    p->right = q->right;
                    q->right = p;
                }
                //需要完成列插入
                if(M->chead[p->j]==NULL || M->chead[p->j]->i>p->i){
                    p->down = M->chead[p->j];
                    M->chead[p->j] = p;
                } else {
                    for (q = M->chead[p->j]; (q->down) && (q->down->i<p->i);q = q->down){}

                    if (q->i==p->i || (q->down) && (q->down->i==p->i)){
                        printf("Repeated position.\n");
                        return ERROR;
                    }
                    p->down = q->down;
                    q->down = p;
                }
            }
        }
    }
    free(tmps);
    va_end(ap);
    return OK;
}

void DestroySMatrix_OL (CrossList *T)
{
    //主要是处理行和列的链表
    OLink row,tmp;
    int i;
    for (i=1;i<=T->mu;i++){
        row = T->rhead[i];
        while (row){
            tmp = row;
            row = row->right;
            free(tmp);
        }
    }
    free(T->rhead);
    free(T->chead);

    T->rhead = T->chead = NULL;
    T->mu = T->nu = T->tu = 0;
}

void PrintSMatrix_OL (CrossList T)
{
    OLink p;
    int i,j;
    for (i=1;i<=T.mu;i++){
        p = T.rhead[i];
        for (j=1;j<=T.mu;j++){
            if (p && p->j==j){
                printf("%d\t",p->e);
                p = p->right;
            } else
                printf("0\t");
        }
        printf("\n");
    }
}

void CopySMatrix_OL (CrossList *T, CrossList M)
{
    T->mu = M.mu;
    T->nu = M.nu;
    T->tu = M.tu;
    int k,i;
    OLink p,q,tmp,tmpcol;
    InitMatrixandChain (T);

    for (i=1;i<=M.mu;i++){
        q = M.rhead[i];
        if (!q)
            continue;
        while (q){
            p = (OLink)malloc(sizeof(OLNode));
            if (!p)
                exit(OVERFLOW);
            p->i = q->i;
            p->j = q->j;
            p->e = q->e;
            p->right = p->down = NULL;
            InserttoChainTable (p,&tmp,tmpcol, T);

            q = q->right;
        }
    }
}

Status AddSMatrix_OL (CrossList *T,CrossList M, CrossList N)
{
    if(M.mu!=N.mu || M.nu!=N.nu){
        printf("Cannot add these two matrix.\n");
        return ERROR;
    }
    int k;
    T->mu = M.mu;
    T->nu = M.nu;
    T->tu = 0;
    InitMatrixandChain (T);

    int row;
    OLink pm,pn,p,tmp,tmpcol;
    for (row=1;row<=M.mu;row++){
        //从第一行遍历
        pm = M.rhead[row];
        pn = N.rhead[row];

        while (pm && pn){
            //当前行均有未扫描的单元
            //区分是否需要创建结点
            if (pm->j==pn->j && pm->e+pn->e==0){
                pm = pm->right;
                pn = pn->right;
                continue;
            }
            p = (OLink)malloc (sizeof(OLNode));
            if (!p)
                exit (OVERFLOW);
            if (pm->j<pn->j){
                p->i = pm->i;
                p->j = pm->j;
                p->e = pm->e;
                pm = pm->right;
            } else if (pm->j>pn->j){
                p->i = pn->i;
                p->j = pn->j;
                p->e = pn->e;
                pn = pn->right;
            } else {
                p->i = pm->i;
                p->j = pm->j;
                p->e = pm->e + pn->e;
                pm = pm->right;
                pn = pn->right;
            }
            //创建完之后处理指针
            p->down = p->right = NULL;
            InserttoChainTable (p,&tmp,tmpcol, T);
        }
        while(pm){
            p = (OLNode*)malloc(sizeof(OLNode));
            if (!p)
                exit (OVERFLOW);
            p->i = pm->i;
            p->j = pm->j;
            p->e = pm->e;
            p->down = p->right = NULL;
            InserttoChainTable (p,&tmp,tmpcol, T);
            pm = pm->right;
        }
        while(pn){
            p = (OLNode*)malloc(sizeof(OLNode));
            if (!p)
                exit (OVERFLOW);
            p->i = pn->i;
            p->j = pn->j;
            p->e = pn->e;
            p->down = p->right = NULL;
            InserttoChainTable (p,&tmp,tmpcol, T);
            pn = pn->right;
        }
    }
    return OK;
}

Status SubSMatrix_OL (CrossList *T, CrossList M, CrossList N)
{
    if(M.mu!=N.mu || M.nu!=N.nu){
        printf("Cannot sub these two matrix.\n");
        return ERROR;
    }
    T->mu = M.mu;
    T->nu = M.nu;
    T->tu = 0;
    InitMatrixandChain (T);

    int row;
    OLink pm,pn,p,tmp,tmpcol;
    for (row=1;row<=M.mu;row++){
        //从第一行遍历
        pm = M.rhead[row];
        pn = N.rhead[row];

        while (pm && pn){
            //当前行均有未扫描的单元
            //区分是否需要创建结点
            if (pm->j==pn->j && pm->e+pn->e==0){
                pm = pm->right;
                pn = pn->right;
                continue;
            }
            p = (OLink)malloc (sizeof(OLNode));
            if (!p)
                exit (OVERFLOW);
            if (pm->j<pn->j){
                p->i = pm->i;
                p->j = pm->j;
                p->e = pm->e;
                pm = pm->right;
            } else if (pm->j>pn->j){
                p->i = pn->i;
                p->j = pn->j;
                p->e = -pn->e;
                pn = pn->right;
            } else {
                p->i = pm->i;
                p->j = pm->j;
                p->e = pm->e - pn->e;
                pm = pm->right;
                pn = pn->right;
            }
            //创建完之后处理指针
            p->down = p->right = NULL;
            InserttoChainTable (p,&tmp,tmpcol, T);
        }
        while(pm){
            p = (OLNode*)malloc(sizeof(OLNode));
            if (!p)
                exit (OVERFLOW);
            p->i = pm->i;
            p->j = pm->j;
            p->e = pm->e;
            p->down = p->right = NULL;
            InserttoChainTable (p,&tmp,tmpcol, T);
            pm = pm->right;
        }
        while(pn){
            p = (OLNode*)malloc(sizeof(OLNode));
            if (!p)
                exit (OVERFLOW);
            p->i = pn->i;
            p->j = pn->j;
            p->e = -pn->e;
            p->down = p->right = NULL;
            InserttoChainTable (p,&tmp,tmpcol, T);
            pn = pn->right;
        }
    }
    return OK;
}

Status MultSMatrix_OL (CrossList *T, CrossList M,CrossList N)
{
    if (M.nu!=N.mu){
        printf("Unable to Multiply.\n");
        return ERROR;
    }
    T->mu = M.mu;
    T->nu = N.nu;
    T->tu = 0;
    InitMatrixandChain(T);

    int mrow,ncol;
    CElemType e;
    OLink pm,pn,p,tmp,tmpcol;

    if (M.tu*N.tu){
        for (mrow=1;mrow<=M.mu;mrow++){
            for (ncol=1;ncol<=N.nu;ncol++){
                pm = M.rhead[mrow];
                pn = N.chead[ncol];
                e=0;

                while (pm && pn){
                    if (pm->j<pn->i)
                        pm = pm->right;
                    else if (pm->j>pn->i)
                        pn = pn->down;
                    else{
                        e+=pm->e*pn->e;
                        pm = pm->right;
                        pn = pn->down;
                    }
                }
                if (e){
                    p = (OLink)malloc(sizeof(OLNode));
                    if (!p)
                        exit(OVERFLOW);
                    p->i = M.rhead[mrow]->i;
                    p->j = N.chead[ncol]->j;
                    p->e = e;
                    p->right = p->down = NULL;
                    InserttoChainTable (p, &tmp, tmpcol, T);
                }
            }
        }
    }
    return OK;
}

void TransposeSMatrix_OL (CrossList *T, CrossList M)
{
    T->mu = M.mu;
    T->nu = M.nu;
    T->tu = M.tu;
    InitMatrixandChain(T);

    int i;
    OLink p,pm,tmp,tmpcol;
    if (T->tu){
        for (i=1;i<=M.nu;i++){
            pm = M.chead[i];
            if (!pm)
                continue;
            while (pm){
                p = (OLink)malloc(sizeof(OLNode));
                if (!p)
                    exit(OVERFLOW);
                p->i = pm->j;
                p->j = pm->i;
                p->e = pm->e;
                p->right = p->down = NULL;
                InserttoChainTable (p, &tmp, tmpcol, T);
                pm=pm->down;
            }
        }
    }
}

Status InserttoChainTable (OLink p, OLink *tmp, OLink tmpcol, CrossList *T)
{
    T->tu++;
    if (T->rhead[p->i]==NULL)
        T->rhead[p->i] = p;
    else
        (*tmp)->right = p;
    *tmp = p;

    if (T->chead[p->j]==NULL || T->chead[p->j]->i>p->i){
        (*tmp)->down = T->chead[p->j];
        T->chead[p->j] = *tmp;
    } else {
        for (tmpcol=T->chead[p->j];(tmpcol->down)&&(tmpcol->down->i<p->i);tmpcol = tmpcol->down){}

        (*tmp)->down = tmpcol->down;
        tmpcol->down = *tmp;
    }
}

Status InitMatrixandChain (CrossList *T)
{
    T->rhead = (OLink *)malloc((T->mu+1)*sizeof(OLink));
    if (!T->rhead)
        exit (OVERFLOW);
    T->chead = (OLink *)malloc((T->nu+1)*sizeof(OLink));
    int k;
    if (!T->chead)
        exit (OVERFLOW);
    for (k=0;k<=T->mu;k++){
        T->rhead[k] = NULL;
    }
    for (k=0;k<=T->nu;k++){
        T->chead[k] = NULL;
    }
    return OK;
}
#endif // CROSSLIST_C

文档中的测试数据:

Row: 5
Col: 5
Num: 10
Data: (1,2,1),(1,4,5),(2,3,-3),(2,5,2),(3,1,2),(3,2,3),(3,3,4),(4,4,2),(5,1,3),(5,2,-1)

Row: 5
Col: 5
Num: 8
Data: (1,1,-3),(1,3,2),(2,4,-1),(3,2,4),(4,1,6),(4,5,5),(5,1,3),(5,3,2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值