数据结构-稀疏矩阵与广义表

稀疏矩阵

/* 
设矩阵 A 中有 s 个非零元素,若 s 远远小于矩阵元素的总数,则称 A 为稀疏矩阵。 
 
这里以一维数组顺序存放非零元素的行号、列号和数值,行号 -1 作为结束标志。  
*/ 
 
#include<stdio.h> 
#define m    6                //用户可根据需要定义原始矩阵行数  
#define n    8                //定义原始矩阵列数  
#define max 50 
 
/*********************************************/  
/*            转储稀疏矩阵的算法             */ 
/*********************************************/  
void CreateMatrix(int A[m][n],int B[50]) 
{ 
    int i,j,k=0; 
    for(i=0;i<m;i++) 
        for(j=0;j<n;j++) 
            if(A[i][j]!=0) 
            { 
                B[k]=i;k++; 
                B[k]=j;k++; 
                B[k]=A[i][j];k++; 
            } 
    B[k]=-1;    //非零元素存储的结束  
}  
 
/*********************************************/  
/*            转储稀疏矩阵的算法             */ 
/*********************************************/  
void MatrixAdd(int A[max],int B[max],int C[max]) 
{ 
    int i=0,j=0,k=0; 
    while(A[i]!=-1 && B[j]!=-1) 
    { 
        if(A[i]==B[j])                //行相等 
        { 
            if(A[i+1]==B[j+1])        //且列相等  
            { 
                C[k]=A[i]; 
                C[k+1]=A[i+1]; 
                C[k+2]=A[i+2]+B[j+2]; 
                k=k+3; 
                i=i+3; 
                j=j+3;     
            }  
            else if(A[i+1]<B[j+1])    //A的列小于B的列,将 A 的三个元素直接存入 C 中 
            { 
                C[k]=A[i]; 
                C[k+1]=A[i+1]; 
                C[k+2]=A[i+2]; 
                k=k+3; 
                i=i+3;  
            }  
            else                    //B的列小于A的列,将B的三个元素直接存入C中  
            { 
                C[k]=B[j]; 
                C[k+1]=B[j+1]; 
                C[k+2]=B[j+2]; 
                k=k+3; 
                j=j+3;     
            } 
        }  
        else if(A[i]<B[j])            //A的行小于B的行,将A的三个元素直接存入C中 
        { 
            C[k]=A[i]; 
            C[k+1]=A[i+1]; 
            C[k+2]=A[i+2]; 
            k=k+3; 
            i=i+3;  
        }  
        else                        //B的行小于A的行,将B的三个元素直接存入C中  
        { 
            C[k]=B[j]; 
            C[k+1]=B[j+1]; 
            C[k+2]=B[j+2]; 
            k=k+3; 
            j=j+3; 
        } 
    }                                //循环结束  
    if(A[i]==-1) 
        while(B[j]!=-1)                //A结束B还有元素,将B的所有元素直接存入C中  
        { 
            C[k]=B[j]; 
            C[k+1]=B[j+1]; 
            C[k+2]=B[j+2]; 
            k=k+3; 
            j=j+3;     
        }  
    else 
        while(A[i]!=-1)                //B结束,A还有元素,将A的所有元素直接存入C中  
        { 
            C[k]=A[i]; 
            C[k+1]=A[i+1]; 
            C[k+2]=A[i+2]; 
            k=k+3; 
            i=i+3;     
        } 
    C[k]=-1; 
}  
 
/*********************************************/  
/*                   主函数                  */ 
/*********************************************/  
void main() 
{ 
    int E[m][n],F[m][n],A[max],B[max],C[max]; 
    int i,j,k; 
    printf("输入E矩阵:\n"); 
    for(i=0;i<m;i++)                //输入E矩阵所有元素值 
        for(j=0;j<n;j++) 
            scanf("%d",&E[i][j]); 
    printf("输入F矩阵:\n"); 
    for(i=0;i<m;i++)                //输入F矩阵所有元素值 
        for(j=0;j<n;j++) 
            scanf("%d",&F[i][j]); 
    CreateMatrix(E,A);                //E矩阵的非零元素存储到一维数组A中 
    CreateMatrix(F,B);                //F矩阵的非零元素存储到一维数组B中  
    MatrixAdd(A,B,C);                //A,B相加存入C 
    i=0; 
    j=0; 
    k=0; 
    printf("A数组内容如下:\n"); 
    while(A[i]!=-1)                    //输出A中内容  
    { 
        printf("%5d,%5d,%5d\n",A[i],A[i+1],A[i+2]); 
        i=i+3;     
    }  
    printf("B数组内容如下;\n"); 
    while(B[j]!=-1) 
    { 
        printf("%5d,%5d,%5d\n",B[j],B[j+1],B[j+2]); 
        j=j+3; 
    } 
    printf("C数组内容如下;\n"); 
    while(C[k]!=-1) 
    { 
        printf("%5d,%5d,%5d\n",C[k],C[k+1],C[k+2]); 
        k=k+3; 
    } 
}  
 
/* 
测试输入: 
E矩阵: 
0 0 3 0 0 0 0 0 
0 0 0 0 0 0 5 0 
0 0 0 0 0 0 0 0 
0 0 0 0 7 0 0 0 
0 0 0 0 0 0 0 0 
0 9 0 0 0 0 0 0 
F矩阵: 
0 2 0 0 0 0 0 0 
0 0 0 4 0 0 0 0 
0 0 0 0 0 6 0 0 
0 0 0 0 8 0 0 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 
*/ 
 

广义表运算

#include<stdio.h> 
#include<stdlib.h> 
 
/*************************/  
/*    广义表的存储结构   */ 
/*************************/ 
typedef char DataType; 
enum{fasle,true}; 
typedef enum{atom,list}NodeTag;        //atom=0,表示原子;list=1,表示子表 
typedef struct GLnode 
{ 
    NodeTag tag;            //用以区分原子结点和表结点 
    union 
    { 
        DataType data;        //用以存放原子结点值,其类型由用户自定义 
        struct GLnode * slink;        //指向子表的指针  
    }; 
    struct GLnode * link;            //指向下一个表结点  
}GLNode,*Glist;            //广义表结点及广义表类型  
 
 
/*************************/  
/*    建立广义表函数     */ 
/*************************/ 
//注:C语言中&(如&a)是取变量a的地址;而C++中&(&a)是变量a的引用(即表示变量a的地址),仅仅只是一个标识而已。 
void CreatGList(Glist GL) 
{ 
    char ch; 
    scanf("%c",&ch); 
    if(ch!=10)                    //如果广义表未结束(10是回车的ASCII码) 
    { 
         
        if(ch=='(') 
        { 
            GL->tag=list; 
            GL->slink=(GLNode *)malloc(sizeof(GLNode)); 
            CreatGList(GL->slink);    //递归调用构造子表  
        } 
        else if (ch == ')')   
            GL = NULL; 
        else 
        { 
            //GL=(GLNode *)malloc(sizeof(GLNode)); 
            //构造原子结点 
            GL->tag=atom; 
            GL->data=ch;  
        }  
    }                            //结束 
    else 
        GL=NULL; 
    scanf("%c",&ch); 
    if(GL!=NULL) 
        if(ch!=10) 
        { 
            if(ch==',') 
            { 
                GL->link=(GLNode *)malloc(sizeof(GLNode)); 
                CreatGList(GL->link);    //递归构造后续广义表 
            } 
            else 
                GL->link=NULL;            //表示遇到 ')'或结束符 ';'时无后续表  
        } 
        else 
            GL->link=NULL; 
} 
 
/*************************************/  
/*           输出广义表函数          */ 
/*************************************/ 
void PrintGList(Glist GL) 
{ 
    if(GL!=NULL) 
    { 
        if(GL->tag==list) 
        { 
            printf("("); 
            if(GL->slink==NULL) 
                printf(" "); 
            else PrintGList(GL->slink);    //递归调用输出子表  
        } 
        else 
            printf("%c",GL->data);        //输出结点数据域值 
        if(GL->tag==list) 
            printf(")"); 
        if(GL->link!=NULL) 
        { 
            printf(","); 
            PrintGList(GL->link);        //递归调用输出下一个结点  
        } 
    } 
}  
 
/*************************************/  
/*           广义表查找函数          */ 
/*************************************/ 
Glist FindGlistX(Glist GL,DataType x,int *mark)  
{    //调用广义表GL所指向的广义表,mark=false,x为查找的元素, 
    //若查找成功,mark=true,p为指向数据域为x的结点  
    if(GL!=NULL) 
    { 
        if(GL->tag==0 && GL->data==x) 
        { 
            *mark=true;  
            return GL;                          
        } 
        else 
            if(GL->tag==1) 
                FindGlistX(GL->slink,x,mark); 
        FindGlistX(GL->link,x,mark); 
    }  
    return NULL; 
}  
 
/*************************************/  
/*          求广义表表头函数         */ 
/*************************************/ 
Glist head(Glist GL) 
{ 
    Glist p; 
    if(GL!=NULL && GL->tag!=0)            //不为空并且不是原子  
    { 
        p=GL->slink; 
        p->link=NULL; 
        return p;                        //返回GL中指向子表的指针     
    } 
    else 
        return NULL;  
}  
 
/*************************************/  
/*          求广义表表尾函数         */ 
/*************************************/ 
Glist tail(Glist GL) 
{ 
    Glist p; 
    if(GL!=NULL && GL->tag!=0)            //表不为空表并且有表尾  
    { 
        p=GL->slink; 
        p=p->link;                        //p指向第二个元素 
        GL->slink=p;                    //删除广义表第一个元素     
    } 
    return p;  
}  
 
/*************************************/  
/*           求广义表深度            */ 
/*************************************/ 
void depth(Glist GL,int *maxdh) 
{ 
    int h; 
    if(GL->tag==0) 
        maxdh=0;                        //说明广义表为单个元素 
    else 
        if(GL->tag==1 && GL->slink==NULL) 
            *maxdh=1;                    //广义表为空表 
        else                            //进行递归求解  
        { 
            GL=GL->slink;                //进入第一层 
            *maxdh=0; 
            do                //循环扫描表的第一层的每个结点,对每个结点求其子表深度  
            { 
                depth(GL,&h); 
                if(h>*maxdh) 
                    *maxdh=h;            //取最大的子表深度 
                GL=GL->link;     
            }while(GL!=NULL); 
            *maxdh=*maxdh+1;                //子表最大深度加1  
        }  
}  
 
/*************************************/  
/*     求广义表的长度(即元素的个数     */ 
/*************************************/ 
//注:GL->slink=NULL 和没有指定空间是不同的。 
int GListLength(Glist GL) 
{ 
    if (GL != NULL) 
        return 1+GListLength(GL->link); 
    else 
        return 0; 
} 
 
/*************************************/  
/*              复制广义表            */ 
/*************************************/ 
void CopyGList(Glist NList,Glist GList) 
{//复制广义表要 
 //将广义表的标记、原子、子表和下一结点复制 
    if (!GList)//原广义表为空 
        NList = NULL; 
    else 
    { 
        NList->tag = GList->tag; 
        if (GList->tag == 0) 
            NList->data = GList->data;//复制广义表的原子结点 
        else if (GList->tag == 1) 
        { 
            if (!(NList->slink = (GLNode *)malloc(sizeof(GLNode)))) 
                printf("存储空间分配失败\n"); 
            CopyGList(NList->slink,GList->slink);//复制广义表的子表 
        } 
            if (!(NList->link = (GLNode *)malloc(sizeof(GLNode)))) 
                    printf("存储空间分配失败\n"); 
            CopyGList(NList->link,GList->link);//复制广义表的下一结点 
        } 
} 
 
/*************************************/  
/*    主函数:广义表基本运算的实现    */ 
/*************************************/ 
int main()                             
{ 
    int xz=1,mark; 
    char x; 
    Glist GL=(GLNode *)malloc(sizeof(GLNode)); 
    Glist GL1,NList;  
    //void CreatGList(Glist GL),PrintGList(Glist GL),depth(Glist GL,int *maxdh); 
    //Glist FindGlistX(Glist GL,DataType x,int *mark),head(Glist GL),tail(Glist GL); 
    while(xz) 
    { 
        printf("*===============================*\n"); 
        printf("*          广义表的运算         *\n"); 
        printf("*===============================*\n"); 
        printf("**********1.建立广义表***********\n"); 
        printf("**********2.广义表查找***********\n"); 
        printf("**********3.求广义表头***********\n"); 
        printf("**********4.求广义表尾***********\n"); 
        printf("**********5.求广义表深度*********\n"); 
        printf("**********6.求广义表长度*********\n"); 
        printf("**********7.输出复制广义表********\n"); 
        printf("**********0.退出表的运算*********\n"); 
        printf("*===============================*\n"); 
        printf("            请 选 择:0-5        \n"); 
        scanf("%d",&xz); 
        getchar(); 
        switch(xz) 
        { 
            case 1: 
                printf("输入广义表:"); 
                CreatGList(GL); 
                printf("输出广义表:"); 
                PrintGList(GL); 
                printf("\n"); 
                break; 
            case 2: 
                printf("输入要查找的数据值(单个字符): "); 
                scanf("%c",&x); 
                mark=fasle; 
                FindGlistX(GL,x,&mark); 
                if(mark) 
                     printf("要查找的数据存在表中!\n"); 
                 else 
                     printf("要查找的数据不在表中!\n"); 
                 break; 
             case 3: 
                 printf("输入要求表头的广义表:"); 
                 CreatGList(GL); 
                 GL1=head(GL); 
                 printf("广义表的表头是:"); 
                 PrintGList(GL1); 
                printf("\n"); 
                break; 
            case 4: 
                printf("输入要求表尾的广义表:"); 
                CreatGList(GL); 
                GL1=tail(GL); 
                 printf("广义表的表尾是:"); 
                 printf("("); 
                 PrintGList(GL1); 
                printf(")"); 
                printf("\n"); 
                GL=NULL; 
                break; 
            case 5: 
                printf("输入要求深度的广义表:"); 
                CreatGList(GL); 
                mark=0; 
                depth(GL,&mark); 
                printf("广义表的深度是:%5d\n",mark); 
                break; 
            case 6: 
                printf("输入要求长度的广义表:"); 
                CreatGList(GL); 
                mark=0; 
                printf("广义表的长度是:%5d\n",GListLength(GL->slink)); 
                break; 
            case 7: 
                if (!(NList = (GLNode *)malloc(sizeof(GLNode)))) 
                    printf("存储空间分配失败\n"); 
                CopyGList(NList,GL); 
                printf("输出复制广义表:"); 
                PrintGList(NList); 
                break; 
            default: 
                printf("再见!\n"); 
                return 0;   
        }  
    }  
} 

版权所有,转载请注明出处 luowei.github.io.