十字链表的定义及C语言描述

2023-11-05 04:58

本文主要是介绍十字链表的定义及C语言描述,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

十字链表常用于表示稀疏矩阵,可视作稀疏矩阵的一种链式表示,因此,这里以稀疏矩阵为背景介绍十字链表。不过,十字链表的应用远不止稀疏矩阵,一切具有正交关系的结构,都可用十字链表存储。

1、存储方式

(a)稀疏矩阵中每个非0元素对应一个十字链表结点,每个结点的结构为

其中各字段的含意为:
row──元素在稀疏矩阵中的行号
col──元素在稀疏矩阵中的列号
val──元素值
down──指向同列中下一个非0元素结点
right──指向同行中下一个非0元素结点

(b)每行/列设一个表头结点(结构同元素结点),以down/right为链构成循环链表,即第i列头结点的down指向该列上第1个非0元素,第i行头结点的right指向该行第1个非0元素。第i列/行上最后一个结点的down/right指向该列/行的头结点。若某列/行中无非0元素,则令它的头结点down/right域指向自己。
      (c)设一个总头结点(结构同元素结点),令总头结点和各个列/行头结点用val字段,按列/行序构成一个循环单链表。

(d)可令总头结点的row,col与val分别表示矩阵的最大行号、列号与非0元素个数,而down/right指向第1列/行的头结点。该总头结点可作为整个十字链表的代表。

 (e)由于行与列的头结点分别使用right域与down域(不同时使用),故第i列与第i行头结点可合用同一个头结点(对所有可能的i),以节省存储空间。
 (f)有时,为了快速访问行/列头结点,设置一个一维数组headNodes[],使headNodes[i]指向i行/列的头结点。但这并不是必须的,因为各行/列的头结点已形成了一个循环单链表,故若已知十字链表总头结点,即可搜索到任一头结点。

设有一个如下形式的矩阵,它所对应的十字链表如下图所示。

 

稀疏矩阵的十字链表存储表示:


#include <malloc.h> 
#include <stdio.h> /*十字链表的结构类型定义如下:*/ typedef struct OLNode 
{ int row,col; /*非零元素的行和列下标*/ int value; struct OLNode *right; /*非零元素所在行表、列表的后继链域*/ struct OLNode *down; 
}OLNode, *OLink; typedef struct 
{ OLink *row_head; /*行、列链表的头指针向量*/ OLink *col_head; int m,n,len; /*稀疏矩阵的行数、列数、非零元素的个数*/ 
}CrossList; /*建立稀疏矩阵的十字链表的算法*/ 
void CreateCrossList(CrossList *M) 
{ int m, n, t, i, j, e; OLNode* p; OLNode* q; /*采用十字链表存储结构,创建稀疏矩阵M*/ scanf("%d%d%d", &m,&n,&t); /*输入M的行数,列数和非零元素的个数*/ M->m=m; M->n=n; M->len=t; if(!(M->row_head=(OLink *)malloc((m+1)*sizeof(OLink)))) exit(OVERFLOW); if(!(M->col_head=(OLink * )malloc((n+1)*sizeof(OLink)))) exit(OVERFLOW); /*初始化行、列头指针向量,各行、列链表为空的链表*/ for(int h=0; h<m+1; h++) { M->row_head[h] = NULL; } for(int t=0; t<n+1; t++) { M->col_head[t] = NULL; } for(scanf("%d%d%d", &i,&j,&e);i!=0;scanf("%d%d%d", &i,&j,&e)) { if(!(p=(OLNode *)malloc(sizeof(OLNode)))) exit(OVERFLOW); p->row=i; p->col=j; p->value=e; /*生成结点*/ if(M->row_head[i]==NULL) M->row_head[i]=p; p->right=NULL; else { /*寻找行表中的插入位置*/ for(q=M->row_head[i];q->right&&q->right->col<j;q=q->right); /*空循环体*/ p->right=q->right; q->right=p; /*完成插入*/ } if(M->col_head[j]==NULL) M->col_head[j]=p; p->down=NULL; else { /*寻找列表中的插入位置*/ for(q=M->col_head[j];q->down&&q->down->row<i;q=q->down); /*空循环体*/ p->down=q->down; q->down=p; /*完成插入*/ } } 
}


这篇关于十字链表的定义及C语言描述的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/347561

相关文章

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

基于Go语言实现一个压测工具

《基于Go语言实现一个压测工具》这篇文章主要为大家详细介绍了基于Go语言实现一个简单的压测工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理客户端模块Http客户端处理Grpc客户端处理Websocket客户端

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ