欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言:十字链表

程序员文章站 2024-03-23 12:41:22
...

C语言:十字链表
实现代码(附注释说明)

#include <malloc.h>
#include <stdio.h>
//十字链表的节点(稀疏矩阵的非零元)定义
typedef struct OLNode
{
int row, col;/*非零元素的行、列坐标*/
int value;/*元素的值*/
struct OLNode *right;/*指向右方的指针*/
struct OLNode *down;/*指向下方的指针*/
}OLNode,*OLink;/*OLink是指向OLNode的指针*/

//十字链表
typedef struct
{
//行链表的头指针
OLink *row_head;/*指针的指针*/
//列链表的头指针
OLink *col_head;
//稀疏矩阵的行数、列数和非零元素的个数
int m, n, len;
}CrossList;

//建立十字链表的函数
void CreateCrossList(CrossList *M)/*M是指向十字链表的指针*/
{
int i, j, e; /*非零元素的行、列坐标和值*/
int m, n, l;/*稀疏矩阵的行数、列数和非零元素的个数*/
OLNode* p;  /*定义两个指向节点的指针*/
OLNode* q;
scanf("%d%d%d", &m, &n, &l);
M->m = m;  /*行数*/
M->n = n;  /*列数*/
M->len = l;  /*非零元素个数*/
if(!(M->row_head=(OLink*)malloc((m+1)*sizeof(OLink))))/*分配好空间*/
{
    printf("Error\n");
}
if(!(M->col_head=(OLink*)malloc((n+1)*sizeof(OLink))))/*分配好空间*/
{
    printf("Error\n");
}
int h;
for(h=0; h<m+1; h++)
{
    M->row_head[h] = NULL;/*将“各”行链表的头指针指空*/
}
int t;
for(t=0; t<n+1; t++)
{
    M->col_head[t] = NULL;/*将“各”列链表的头指针指空*/
}

for(scanf("%d%d%d", &i, &j, &e); m!=0; scanf("%d%d%d",&i, &j, &e))/*输入元素的行、列坐标以及值,要按坐标顺序输入*/
{
    if(!(p = (OLNode*)malloc(sizeof(OLNode))))/*给节点分配空间*/
    {
        printf("Error\n");
    }
    //生成节点
    p->row = i;
    p->col = j;
    p->value = e;
    if(M->row_head[i] == NULL)/*该行尚无非零元的情况*/
    {
        M->row_head[i] = p;/*p就是该行第一个非零元(各头指针只能直接指向该行/列的第一个非零元)*/
    }
    else/*不是第一个非零元,可能已有一个、两个或多个非零元*/
        //在此仅以第一次执行以下操作举例分析来说明这些语句可以在上面任何情况下把我们输入的节点插入到合适的位置
    {  //不管进入不进入循环,q=M->row_head[i]一定执行
        for(q=M->row_head[i]; q->right && q->right->col < j; q=q->right);
        //满足循环条件(第一次执行时)意为至少有两个非零元,且第二个的列坐标比我们输入的节点的要小
        {
        p->right = q->right;/*让所输入节点的right指针指向原来的第二个节点*/
        }
        //执行下句分为经历过循环和没经历过循环两种情况
        //未进入过循环的情况(不满足循环条件)
        //1.只有一个非零元时,执行此操作意为直接插在后面,成为第二个节点ps.这要求我们输入的坐标值要按顺序
        //2.有两个非零元,但第二个非零元的列坐标比我们输入的要大,依然插在第一个非零元后面,成为老二
        //进入过循环的情况
        //这里只说执行了一次循环然后退出的情况(接上面循环结构里的注释):在进行了q=q->right这一操作后,
        //不管原来是没有第三个节点还是第三个节点的列坐标比输入的大,输入的节点都将成为第三个节点
        q->right = p;/*q的意义??*/
    }
         //接下来是在列中插入,与在行中插入方法相同,不再阐释
    if(M->col_head[j] == NULL)
    {
        M->col_head[j] = p;
    }
    else
    {
        for(q=M->col_head[j]; q->down && q->down->row < i; q=q->down);
        {
        p->down = q->down;
        }
        q->down = p;
    }
}/*p是指针,存储的是所输入节点的地址,之后重新赋值,并不会影响之前的节点*/
}