十字链表 Orthogonal List

本文介绍如何使用十字链表来存储稀疏矩阵,并提供了一个具体的实现案例。通过定义结构体和相关操作函数,实现了稀疏矩阵的有效存储与遍历。

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

十字链表,用于存储 稀疏矩阵 或 有向图。

在实现非二元LDPC码译码过程中,需要用十字链表存储校验矩阵H。

网上找到 博客 http://blog.youkuaiyun.com/zhuyi2654715/article/details/6729783 讲解的十分清晰

上图可以 清晰地展现十字链表的数据结构 : 整个十字链表的头指针指向横向和纵向的头指针数组,再由每个对应行和列上的头指针作为链表头,指向各个稀疏节点。

#include <stdio.h>
#include <malloc.h>

typedef struct olnode
{
	int i;//表示矩阵的行号
	int j;//表示矩阵的列号
	int value;//或者值的类型设为element_type
	struct olnode *right;//横向下一个节点的地址
	struct olnode *down; //纵向下一个节点的地址
}olnode,*olist;

typedef struct crosslist
{
	olist *rhead,*chead;
	int rownum;//矩阵行数
	int colnum;//矩阵列数
	int elenum;//矩阵非零元素数
}crosslist;

void creatOList(crosslist *H);
void display(crosslist *H);

void creatOList(crosslist *H)
{
	FILE *fp;
	fp = fopen("Orthogonal_List_matrix.txt","r");

	int i,j;
	int m,n,ele;//不要直接把数据读入数据结构中,设置中间值,进行检测,确定后拷贝到数据结构中
	olnode *p,*q;
	int flag;

	//建立稀疏矩阵,且用十字链表存储
	if (H->rhead)//如果原先存在,销毁
	{
		//destroy();
	}
	do
	{
		flag = 1;
		//printf("输入需要创建的矩阵的行数、列数以及非零元的个数\n");
		fscanf(fp,"%d%d%d",&m,&n,&ele);
		if (m<0||n<0||ele<0||ele>m*n)
		{
			flag = 0;
		}
	}
	while (!flag);
	H->rownum = m;
	H->colnum = n;
	H->elenum = ele;
	//创建横向和纵向的 头指针数组 ,并初始化
	H->rhead = (olist*)malloc(sizeof(olist)*(H->rownum+1));
	//H->chead = (olnode*)malloc(sizeof(olnode)*(H->colnum+1));
	H->chead = (olist*)malloc(sizeof(olist)*(H->colnum+1));
	if (!H->rhead||!H->chead)
	{
		exit(-1);
	}
	for (i = 1;i<H->rownum+1 ;i++ )
	{
		H->rhead[i] = NULL;
	}
	for (i = 1;i<H->colnum+1 ;i++ )
	{
		H->chead[i] = NULL;
	}
	//输入节点并插入表中
	i = 1;
	while (i<=H->elenum)
	{
		do
		{
			flag = 1;
			//printf("输入第%d个结点行号、列号以及值",i);
			//scanf("%d%d%d",&m,&n,&ele);
			fscanf(fp,"%d%d%d",&m,&n,&ele);
			if (m<0||n<0)
			{
				flag = 0;
			}
			else
				i++;
		}
		while (!flag);
		p = (olnode*)malloc(sizeof(olnode));//建立新节点并存入数据
		if (!p)
		{
			exit(-1);
		}
		p->i = m;
		p->j = n;
		p->value = ele;
		//将节点插入
		/*插入的两种情况:
		1.这一行中没有节点=>直接插入
		2.这一行中有节点=>找到正确位置插入
		*/
		//行
		if (H->rhead[m] == NULL || H->rhead[m]->j > n)//一行为空或者为一行中下标最小的...试试把插入合在一起
		{
			p->right = H->rhead[m];//插入在第一个节点
			H->rhead[m] = p;//头指针指向第一个节点
		}
		else
		{
			//在一行中从头寻找插入位置
			for (q = H->rhead[m]; q->right && q->right->j < n ;q = q->right );
			p->right = q->right;
			q->right = p;
		}
		//列
		if (H->chead[n] == NULL || H->chead[n]->j > m)
		{
			p->down = H->chead[n];
			H->chead[n] = p;
		}
		else
		{
			for (q = H->chead[n];q->down && q->down->i < m ;q = q->down );
			p->down = q->down;
			q->down = p;
		}
	}
}
void display(crosslist *H)
{
	int i;
	olnode *p;
	for (i = 1;i<=H->rownum ;i++ )
	{
		p = H->rhead[i];
		while (p)
		{
			printf("(%d,%d)=%d\n",p->i,p->j,p->value);
			p = p->right;
		}
	}
}
int main()
{
	crosslist *H;
	H = (crosslist*)malloc(sizeof(crosslist));
	creatOList(H);
	display(H);
	return 0;
}

实现时,由于读取校验矩阵H时需要链表是双向的,才能进行双向读取,所有每个节点需要再加入两个指针,如下:

typedef struct pnode
{
	int value;//a = 0 ~ q-1
	int col;
	int row;
	pnode *right,*left,*up,*down;
	//double *pmn;
}pnode,*plist;
typedef struct crosslist
{
	plist* right;
	plist* down;
}crosslist;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值