数组(array),在c语言里是最早接触到的数据结构。但是如果作为数据结构这门课来学,在c中学到的关于它的知识,还不足够。
数组的分类:
按物理结构来看,数组分为顺序结构和链式结构。
在顺序结构里,即便是多维数组(矩阵,Matrix),它还是按一维的形式存放在一组连续的存储空间里(别无他选)。一般有两种实现方法:按行顺序存储,称为以行为主(Row Major Order)。c、PASCAL等都采用这种方式。
按列顺序存储,称为以列为主(Column Major Order),FORTRAN使用这种结构。
数组还分为静态存储和动态存储。
静态的就是,int array[10] = {……};这种。
动态存储的是,int * array = new int[10];这一种。动态存储的区别就在于,是实例化后,才分配空间的,是动态地建立和撤销。
矩阵的存储:
矩阵的存储,可以是像每个元素都有独立的空间,还有一种就是压缩存储。即是对为多个值相同的元素,只分配一个存储空间,对零元素不分配空间。这是压缩存储的定义,也是我们在设计程序的效果体现。
如果值相同的元素或者零元素,在矩阵中的分布有一定额规律,即称为特殊矩阵反之为稀疏矩阵(Sparse Matrix )。
对称矩阵、三角矩阵、三对角矩阵都算是特殊矩阵。设计他们的压缩存储,其实思路不难。
稀疏矩阵的压缩存储,有三元组表,和链式结构的十字链表(Orthogonal List)。三元组表,即是(x坐标,y坐标,val值),只有有数值的才存储,0元素就不存储。这种方法在进行转置运算等非零个数在运算中保持不变时,有效。
但是在做加减等运算时,非零元素位置会变化,不适合三元组表。一般采用十字链表结构。不过,好像正统的定义是,每一行每一列都做一个链表,m行n列则需要m x n个链表了。而且每一个结点是由5个域组成:行域(row)、列域(column)、值域(val)、向下域(down)、向右域(right)。每个域都要有相应的值。
我在设计的时候,没认真看,以为总共row一个链表,column一个链表。就只有两个。
以下程序就算是半成品的十字链表吧:
结点的结构体类型和整个十字链表的结构体类型
typedef struct Olnode{
int row,column;
elementype val;
struct Olnode * right;
struct Olnode *down;
}Olnode ,*Olchain;
typedef struct Crosschain{
int rownum,colnum;
struct Olink *rowhead, * colhead;
}Crosschain;
各个函数:
void insertNodeColumn(Olchain colhead,elementype val,int column);
void insertNodeRow(Olchain rowhead,elementype val,int row);
void insertCrossChain(Crosschain * CrossChain,elementype val,int row,int column);
void printNode(Crosschain * CrossChain);
void printColumn(Olchain colhead);
void printRow(Olchain rowhead);
void deleteNode(Crosschain * CrossChain,elementype val);
void deleteNodeColumn(Olchain colhead,elementype val);
void deleteNodeRow(Olchain rowhead,elementype val);
void destroyChain(Crosschain * CrossChain);
void destroyColumn(Olchain colhead);
void destroyRow(Olchain rowhead);
插入函数:
void insertCrossChain(Crosschain * CrossChain,elementype val,int row,int column)
{
insertNodeColumn(CrossChain->colhead,val,column);
insertNodeRow(CrossChain->rowhead,val,row);
printf("insert the CrossChain is succeed\n");
}
void insertNodeColumn(Olchain colhead,elementype val,int column)
{
Olchain NodetoColumn = (Olnode *)malloc(sizeof(Olnode));
NodetoColumn->val = val;
NodetoColumn->column = column;
NodetoColumn->right = NULL;
Olchain TempNode = colhead;
while(TempNode->right != NULL){
if((TempNode->column < column) &&((TempNode->right->column > column)|(TempNode->right->column == column))){
NodetoColumn->right = TempNode->right;
TempNode->right = NodetoColumn;
}
else{
TempNode = TempNode->right;
}
}
if(TempNode->right == NULL){
NodetoColumn->right = TempNode->right;
TempNode->right = NodetoColumn;
}
printf("insert the column is succeed\n");
}
void insertNodeRow(Olchain rowhead,elementype val,int row)
{
Olchain NodetoRow = (Olnode *)malloc(sizeof(Olnode));
NodetoRow->val = val;
NodetoRow->row = row;
NodetoRow->down = NULL;
Olchain TempNode = rowhead;
while(TempNode->down != NULL){
if((TempNode->row < row) &&((TempNode->down->row > row)|(TempNode->down->row == row))){
NodetoRow->down = TempNode->down;
TempNode->down = NodetoRow;
}
else{
TempNode = TempNode->down;
}
}
if(TempNode->down == NULL){
NodetoRow->down = TempNode->down;
TempNode->down = NodetoRow;
}
printf("insert the row is succeed\n");
}
print函数:
void printNode(Crosschain * CrossChain)
{
printColumn(CrossChain->colhead);
printf("\n");
printRow(CrossChain->rowhead);
printf("\n");
}
void printColumn(Olchain colhead)
{
Olchain TempNode = colhead;
while(TempNode->right != NULL ){
printf("(%d,%d) ",TempNode->column,TempNode->val);
TempNode = TempNode->right;
}
if(TempNode->right == NULL){
printf("(%d,%d) ",TempNode->column,TempNode->val);
}
}
void printRow(Olchain rowhead)
{
Olchain TempNode = rowhead;
while(TempNode->down != NULL ){
printf("(%d,%d) ",TempNode->row,TempNode->val);
TempNode = TempNode->down;
}
if(TempNode->down == NULL){
printf("(%d,%d) ",TempNode->row,TempNode->val);
}
}
删除数值函数:
void deleteNode(Crosschain * CrossChain,elementype val)
{
deleteNodeColumn(CrossChain->colhead, val);
deleteNodeRow(CrossChain->rowhead,val);
}
void deleteNodeColumn(Olchain colhead,elementype val)
{
Olchain Tempchain = colhead;
int STATUS = 0;
//这个设计是非常好的,有两个暂时的,同个类型的struct 变量
while(Tempchain->right != NULL ){
Olchain TempNode = Tempchain->right;
if(TempNode->val == val){
Tempchain->right = TempNode->right;
free(TempNode);
printf("delete %d in the column\n",val);
printf("data is 1\n");
STATUS = 1;
}
else Tempchain = Tempchain->right;
printf("data is 2\n");
}
if(Tempchain->val == val){
Tempchain = NULL;
free(Tempchain);
printf("data is 3\n");
STATUS = 1;
printf("delete %d in the column\n",val);
printf("data is 4\n");
}
if(STATUS == 0){
printf("no such data\n");
}
}
//delete这个一直是需要思考的地方,很高兴发现并修复了bug
// 1-设计是非常好的,有两个暂时的,同个类型的struct 变量
//2-while这里需要加if-else,else一定要加,不然会让if执行完再必然地执行下一句,等于跳了两次。有一个量没检测。
//更重要的是,有可能这么一跳,把 Tempchain自己跳到null了,会崩溃
void deleteNodeRow(Olchain rowhead,elementype val)
{
Olchain Tempchain = rowhead;
int STATUS = 0;
printf("data 1\n");
//这个设计是非常好的,有两个暂时的,同个类型的struct 变量
while(Tempchain->down != NULL ){
Olchain TempNode = Tempchain->down;
printf("data 2\n");
if(TempNode->val == val){
Tempchain->down = TempNode->down;
free(TempNode);
STATUS = 1;
printf("delete %d in the row\n",val);
}
else Tempchain = Tempchain->down;
printf("data 3\n");
}
if(Tempchain->val == val){
//Tempchain->right = TempNode->right;
printf("data 4\n");
Tempchain = NULL;
free(Tempchain);
printf("delete %d in the row\n",val);
printf("data 5\n");
STATUS = 1;
}
if(STATUS == 0){
printf("no such data\n");
}
}
destroy函数:
void destroyChain(Crosschain * CrossChain)
{
destroyColumn(CrossChain->colhead);
printf("destroy 1\n");
destroyRow(CrossChain-> rowhead);
}
//很高兴,bug很清楚,这里不能删掉colhead和rowhead,否则就是没有头结点,会崩溃的,需要在main里删除
void destroyColumn(Olchain colhead)
{
while(colhead->right != NULL){
Olchain TempNode = colhead->right;
colhead->right = TempNode->right;
free(TempNode);
}
printf("destroy column is finished\n");
}
void destroyRow(Olchain rowhead)
{
while(rowhead->down != NULL){
Olchain TempNode = rowhead->down;
rowhead->down = TempNode->down;
free(TempNode);
}
printf("destroy row is finished\n");
}
附上完整程序:
#include<stdio.h>
#include<malloc.h>
/*
功能分析:
这种十字链表结构,针对的对象是稀疏矩阵
所以不用全部显示和载入(这恰恰是麻烦的地方)
应该是插入的时候,做判断, 取出/删除时, 不做判断
函数:init(还是把它放在main里面)——print——insert——delete——destroy
两个bug的发现和修复(逻辑的严密性太重要了)!!!!
*/
typedef int elementype;
typedef struct Olnode{
int row,column;
elementype val;
struct Olnode * right;
struct Olnode *down;
}Olnode ,*Olchain;
typedef struct Crosschain{
int rownum,colnum;
struct Olink *rowhead, * colhead;
}Crosschain;
//void insertNode(Olchain OLChain,elementype val,int row,int colum);
void insertNodeColumn(Olchain colhead,elementype val,int column);
void insertNodeRow(Olchain rowhead,elementype val,int row);
void insertCrossChain(Crosschain * CrossChain,elementype val,int row,int column);
void printNode(Crosschain * CrossChain);
void printColumn(Olchain colhead);
void printRow(Olchain rowhead);
void deleteNode(Crosschain * CrossChain,elementype val);
void deleteNodeColumn(Olchain colhead,elementype val);
void deleteNodeRow(Olchain rowhead,elementype val);
void destroyChain(Crosschain * CrossChain);
void destroyColumn(Olchain colhead);
void destroyRow(Olchain rowhead);
int main()
{
Olchain rowhead = (Olnode *)malloc(sizeof(Olnode));
Olchain colhead = (Olnode *)malloc(sizeof(Olnode));
rowhead->row = -1;
rowhead->val = 0;
rowhead->down = NULL;
colhead->column = -1;
colhead->val = -1;
colhead->right = NULL;
Crosschain * CrossChain = (Crosschain *)malloc(sizeof(Crosschain));
CrossChain->rownum = 0;
CrossChain->colnum = 0;
CrossChain->rowhead = rowhead;
CrossChain->colhead = colhead;
insertCrossChain(CrossChain,23,3,2);
printNode(CrossChain);
insertCrossChain(CrossChain,34,4,3);
printNode(CrossChain);
//insertCrossChain(CrossChain,44,4,4);
//printNode(CrossChain);
deleteNode(CrossChain, 34);
deleteNode(CrossChain, 35);
destroyChain(CrossChain);
return 0;
}
void insertCrossChain(Crosschain * CrossChain,elementype val,int row,int column)
{
insertNodeColumn(CrossChain->colhead,val,column);
insertNodeRow(CrossChain->rowhead,val,row);
printf("insert the CrossChain is succeed\n");
}
void insertNodeColumn(Olchain colhead,elementype val,int column)
{
Olchain NodetoColumn = (Olnode *)malloc(sizeof(Olnode));
NodetoColumn->val = val;
NodetoColumn->column = column;
NodetoColumn->right = NULL;
Olchain TempNode = colhead;
while(TempNode->right != NULL){
if((TempNode->column < column) &&((TempNode->right->column > column)|(TempNode->right->column == column))){
NodetoColumn->right = TempNode->right;
TempNode->right = NodetoColumn;
}
else{
TempNode = TempNode->right;
}
}
if(TempNode->right == NULL){
NodetoColumn->right = TempNode->right;
TempNode->right = NodetoColumn;
}
printf("insert the column is succeed\n");
}
void insertNodeRow(Olchain rowhead,elementype val,int row)
{
Olchain NodetoRow = (Olnode *)malloc(sizeof(Olnode));
NodetoRow->val = val;
NodetoRow->row = row;
NodetoRow->down = NULL;
Olchain TempNode = rowhead;
while(TempNode->down != NULL){
if((TempNode->row < row) &&((TempNode->down->row > row)|(TempNode->down->row == row))){
NodetoRow->down = TempNode->down;
TempNode->down = NodetoRow;
}
else{
TempNode = TempNode->down;
}
}
if(TempNode->down == NULL){
NodetoRow->down = TempNode->down;
TempNode->down = NodetoRow;
}
printf("insert the row is succeed\n");
}
void printNode(Crosschain * CrossChain)
{
printColumn(CrossChain->colhead);
printf("\n");
printRow(CrossChain->rowhead);
printf("\n");
}
void printColumn(Olchain colhead)
{
Olchain TempNode = colhead;
while(TempNode->right != NULL ){
printf("(%d,%d) ",TempNode->column,TempNode->val);
TempNode = TempNode->right;
}
if(TempNode->right == NULL){
printf("(%d,%d) ",TempNode->column,TempNode->val);
}
}
void printRow(Olchain rowhead)
{
Olchain TempNode = rowhead;
while(TempNode->down != NULL ){
printf("(%d,%d) ",TempNode->row,TempNode->val);
TempNode = TempNode->down;
}
if(TempNode->down == NULL){
printf("(%d,%d) ",TempNode->row,TempNode->val);
}
}
void deleteNode(Crosschain * CrossChain,elementype val)
{
deleteNodeColumn(CrossChain->colhead, val);
deleteNodeRow(CrossChain->rowhead,val);
}
void deleteNodeColumn(Olchain colhead,elementype val)
{
Olchain Tempchain = colhead;
int STATUS = 0;
//这个设计是非常好的,有两个暂时的,同个类型的struct 变量
while(Tempchain->right != NULL ){
Olchain TempNode = Tempchain->right;
if(TempNode->val == val){
Tempchain->right = TempNode->right;
free(TempNode);
printf("delete %d in the column\n",val);
printf("data is 1\n");
STATUS = 1;
}
else Tempchain = Tempchain->right;
printf("data is 2\n");
}
if(Tempchain->val == val){
Tempchain = NULL;
free(Tempchain);
printf("data is 3\n");
STATUS = 1;
printf("delete %d in the column\n",val);
printf("data is 4\n");
}
if(STATUS == 0){
printf("no such data\n");
}
}
//delete这个一直是需要思考的地方,很高兴发现并修复了bug
// 1-设计是非常好的,有两个暂时的,同个类型的struct 变量
//2-while这里需要加if-else,else一定要加,不然会让if执行完再必然地执行下一句,等于跳了两次。有一个量没检测。
//更重要的是,有可能这么一跳,把 Tempchain自己跳到null了,会崩溃
void deleteNodeRow(Olchain rowhead,elementype val)
{
Olchain Tempchain = rowhead;
int STATUS = 0;
printf("data 1\n");
//这个设计是非常好的,有两个暂时的,同个类型的struct 变量
while(Tempchain->down != NULL ){
Olchain TempNode = Tempchain->down;
printf("data 2\n");
if(TempNode->val == val){
Tempchain->down = TempNode->down;
free(TempNode);
STATUS = 1;
printf("delete %d in the row\n",val);
}
else Tempchain = Tempchain->down;
printf("data 3\n");
}
if(Tempchain->val == val){
//Tempchain->right = TempNode->right;
printf("data 4\n");
Tempchain = NULL;
free(Tempchain);
printf("delete %d in the row\n",val);
printf("data 5\n");
STATUS = 1;
}
if(STATUS == 0){
printf("no such data\n");
}
}
void destroyChain(Crosschain * CrossChain)
{
destroyColumn(CrossChain->colhead);
printf("destroy 1\n");
destroyRow(CrossChain-> rowhead);
}
//很高兴,bug很清楚,这里不能删掉colhead和rowhead,否则就是没有头结点,会崩溃的,需要在main里删除
void destroyColumn(Olchain colhead)
{
while(colhead->right != NULL){
Olchain TempNode = colhead->right;
colhead->right = TempNode->right;
free(TempNode);
}
printf("destroy column is finished\n");
}
void destroyRow(Olchain rowhead)
{
while(rowhead->down != NULL){
Olchain TempNode = rowhead->down;
rowhead->down = TempNode->down;
free(TempNode);
}
printf("destroy row is finished\n");
}
效果: