看数据结构写代码(21) 稀疏矩阵(十字链表方式)
Posted clnchanpin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了看数据结构写代码(21) 稀疏矩阵(十字链表方式)相关的知识,希望对你有一定的参考价值。
写完 这个样例,花费了 我不少时间。大部分时间 花费在 调试 内存问题上。
比如在销毁十字链表时。多次释放节点空间,造成 _CrtIsValidHeapPointer(pUserData) 异常。
当使用malloc 分配 一个 空间时,会将这个空间的起始地址和长度 加到一个链表中去。free(p)的时候 ,会从 链表里 查找 是否 有 这个地址空间,找到了就将这个节点从链表中删除。_CrtIsValidHeapPointer(pUserData) 这个函数 正是 检查 这个空间是否 在链表里,若在,返回 true,否则返回 flase,。
多次 释放节点空间,必然 造成 _CrtIsValidHeapPointer(pUserData) 异常。
仅仅要释放的 不是 分配的起始 地址 都会 报 这个异常。
还有 一个 地方,就是 使用了 释放的 空间的数据。
c/c++ 内存问题。是个 头疼的问题。
以下 进入 正题:
稀疏矩阵 的 十字链表 方式,是 给 全部的行 和 列 都 当成 一个 链表 来处理。
第 i 行 j列的 非0 节点,既在 第 i行的链表上,又在 第 j列的 链表上,所以 叫 十字链表。
结构图例如以下:
以下 上代码
欢迎指出代码不足
// CrossList.cpp : 定义控制台应用程序的入口点。 //稀疏矩阵的十字链表实现 #include "stdafx.h" #include <stdlib.h> typedef int ElementType; enum E_State { E_State_Error = 0, E_State_Ok = 1, }; struct MatrixNode { int row; int col; ElementType data; MatrixNode * rightNext; MatrixNode * downNext; }; MatrixNode * makeNode(int row,int col,ElementType data){ MatrixNode * newNode = (MatrixNode *) malloc(sizeof(MatrixNode)); if (newNode != NULL) { newNode->row = row; newNode->col = col; newNode->data = data; newNode->rightNext = NULL; newNode->downNext = NULL; } return newNode; } //十字链表 struct CrossList { MatrixNode ** rowHead; MatrixNode ** colHead; int rowNum; int colNum; int totalNum; }; E_State listInit(CrossList * list,int row,int col){ list->rowHead = (MatrixNode**)malloc(sizeof(MatrixNode*) * row); list->colHead = (MatrixNode**)malloc(sizeof(MatrixNode*) * col); if (list->rowHead && list->colHead) { list->rowNum = row; list->colNum = col; list->totalNum = 0; //建立头指针节点 for (int i = 0; i < row; i++) { list->rowHead[i] = makeNode(-1,-1,-1); if (list->rowHead[i] == NULL) { return E_State_Error; } } for (int i = 0; i < col; i++) { list->colHead[i] = makeNode(-1,-1,-1); if (list->colHead[i] == NULL) { return E_State_Error; } } return E_State_Ok; } return E_State_Error; } //销毁十字链表 void listDestory(CrossList * list){ //销毁链表节点 for (int i = 0; i < list->rowNum; i++) { MatrixNode * head = list->rowHead[i]; MatrixNode * next = head->rightNext; while (next != NULL) { MatrixNode * freeNode = next; next = next->rightNext; free(freeNode); } //别忘了销毁头节点 free(head); } for (int i = 0; i < list->colNum; i++) { MatrixNode * head = list->colHead[i]; free(head); /*销毁了两遍,呵呵 MatrixNode * next = head->downNext; while (next != NULL) { MatrixNode * freeNode = next; next = next->downNext; free(freeNode); }*/ } free(list->colHead); free(list->rowHead); list->colHead = NULL; list->rowHead = NULL; list->rowNum = 0; list->colNum = 0; list->totalNum = 0; } //在 row 行 col 列 插入 一个 data 元素(从 0行。0列 開始) E_State listInsert(CrossList * list,ElementType data,int row,int col){ if (row < 0 || row >= list->rowNum || col >= list->colNum || col < 0) { return E_State_Error; } MatrixNode * newNode = makeNode(row,col,data); if (newNode != NULL) { //增加行链表 MatrixNode * pre = list->rowHead[row]; MatrixNode * next = pre->rightNext; while (next != NULL)//寻找 第一个列值 小于 col 的节点 { if (next->col > col) { break; } pre = next; next = next ->rightNext; } newNode->rightNext = pre->rightNext; pre->rightNext = newNode; //加到列链表 pre = list->colHead[col]; next = pre->downNext; while (next != NULL)//寻找 第一个列值 小于 col 的节点 { if (next->row > row) { break; } pre = next; next = next ->downNext; } newNode->downNext = pre->downNext; pre->downNext = newNode; list->totalNum ++; return E_State_Ok; } return E_State_Error; } //row ,col 从 0行 0 列 開始 E_State listDelete(CrossList * list,int row,int col,ElementType * delData){ if (row >= list->rowNum || row < 0 || col >= list->colNum || col <0) { return E_State_Error; } *delData = 0; //查找行链表 MatrixNode * pre = list->rowHead[row]; MatrixNode * next = pre->rightNext; while (next != NULL) { if (next->col == col) { pre->rightNext = next->rightNext; break; } else if(next->col > col)// 删除的节点 值域为0 { return E_State_Ok; } pre = next; next = next->rightNext; } //查找列链表 pre = list->colHead[col]; next = pre->downNext; while (next != NULL) { if (next->row == row) { pre->downNext = next->downNext; *delData = next->data; list->totalNum --; //在查找完了 列链表之后 才干 释放 空间,要不 会内存 错误. free(next); break; } else if(next->row > row)// 删除的节点 值域为0 { return E_State_Ok; } pre = next; next = next->downNext; } return E_State_Ok; } //list1 = list1 + list2 E_State listAdd(CrossList * list1,CrossList list2){ if (list1->rowNum != list2.rowNum || list1->colNum != list2.colNum) { return E_State_Error; } for (int row = 0; row < list1->rowNum; row++) { MatrixNode * next1 = list1->rowHead[row]->rightNext; MatrixNode * next2 = list2.rowHead[row]->rightNext; while (next1 && next2) { int col1 = next1->col; int col2 = next2->col; if (col1 == col2)//元素 同行 同列 { ElementType sum = next1->data + next2->data; if (sum == 0)//相加为0 { ElementType del; next1 = next1->rightNext;//跟下一句颠倒过来。会有内存错误 listDelete(list1,row,col1,&del); } else//相加不为0 { next1->data = sum; next1 = next1->rightNext; } next2 = next2->rightNext; } else if(col1 < col2)//元素1 小于 元素2 的 列 { next1 = next1->rightNext; } else//元素1 大于 元素2的列,插入元素2 { listInsert(list1,next2->data,row,col2); next2 = next2->rightNext; } } //插入剩余的 next2 元素 while (next2 != NULL ) { listInsert(list1,next2->data,row,next2->col); next2 = next2->rightNext; } } return E_State_Ok; } // list1 = list1 - list2 E_State listSub(CrossList * list1,CrossList list2){ if (list1->rowNum != list2.rowNum || list1->colNum != list2.colNum) { return E_State_Error; } for (int i = 0; i < list2.rowNum; i++) { MatrixNode * next = list2.rowHead[i]->rightNext; while (next != NULL) { next->data = -next->data; next = next->rightNext; } } return listAdd(list1,list2); } //list3 = list1 * list2 E_State listMult(CrossList list1, CrossList list2,CrossList * list3){ if (list1.colNum != list2.rowNum) { return E_State_Error; } listInit(list3,list1.rowNum,list2.colNum); for (int row = 0; row < list1.rowNum; row++) { for (int col = 0; col < list2.colNum; col++) { MatrixNode * nextCol2 = list2.colHead[col]->downNext; ElementType mul = 0; while (nextCol2) { MatrixNode * nextRow1 = list1.rowHead[row]->rightNext; while (nextRow1) { if (nextRow1->col == nextCol2->row) { mul += nextRow1 -> data * nextCol2 ->data; } nextRow1 = nextRow1->rightNext; } nextCol2 = nextCol2->downNext; } if (mul != 0) { listInsert(list3,mul,row,col); } } } return E_State_Ok; } void listTraverse(CrossList list){ printf("--------------------遍历開始-----------------\n"); for (int i = 0; i < list.rowNum; i++) { MatrixNode * next = list.rowHead[i]->rightNext; while (next != NULL) { printf("%d行 %d列 : %d\n",next->row+1,next->col+1,next->data); next = next->rightNext; } } printf("--------------------遍历结束------------------\n"); } int initData[5][10] = { {1,0,0,0,0,0,0,0,0,0}, {0,0,2,0,0,0,0,0,5,0}, {0,0,0,3,0,0,0,0,0,0}, {0,2,0,0,0,0,0,0,0,0}, {1,0,0,0,0,0,0,0,0,9}, }; int initAddData[5][10]= { {1,0,0,0,3,0,0,0,0,0}, {0,0,2,0,4,0,0,0,5,0}, {0,0,0,3,0,0,0,0,0,0}, {0,2,0,0,2,0,0,0,0,0}, {1,0,0,0,1,0,0,0,0,9}, }; int initData2 [10][2] = { {1,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,6}, {0,0}, {0,0}, {5,0}, {0,0}, }; int _tmain(int argc, _TCHAR* argv[]) { //初始化数据 printf("--------------------矩阵1------------\n"); CrossList list1; listInit(&list1,5,10); for (int i = 0; i < 5; i++) { for (int j = 0; j < 10; j++) { int data = initData[i][j]; if (data != 0) { listInsert(&list1,data,i,j); } } } listTraverse(list1); printf("--------------------矩阵2------------\n"); CrossList list2; listInit(&list2,5,10); for (int i = 0; i < 5; i++) { for (int j = 0; j < 10; j++) { int data = initAddData[i][j]; if (data != 0) { listInsert(&list2,data,i,j); } } } listTraverse(list2); printf("--------------------矩阵1 = 矩阵1 + 矩阵2------------\n"); listAdd(&list1,list2); listTraverse(list1); printf("--------------------矩阵1 = 矩阵1 - 矩阵2------------\n"); listSub(&list1,list2); listTraverse(list1); printf("--------------------矩阵3------------\n"); CrossList list3; listInit(&list3,10,2); for (int i = 0; i < 10; i++) { for (int j = 0; j < 2; j++) { int data = initData2[i][j]; if (data != 0) { listInsert(&list3,data,i,j); } } } listTraverse(list3); printf("--------------------矩阵4 = 矩阵1 * 矩阵3------------\n"); CrossList list4; listMult(list1,list3,&list4); listTraverse(list4); //释放内存空间 listDestory(&list1); listDestory(&list2); listDestory(&list3); listDestory(&list4); return 0; }执行截图:
以上是关于看数据结构写代码(21) 稀疏矩阵(十字链表方式)的主要内容,如果未能解决你的问题,请参考以下文章