您的位置:首页 > 理论基础 > 数据结构算法

看数据结构写代码(21) 稀疏矩阵(十字链表方式)

2015-03-18 15:30 483 查看
写完 这个例子,花费了 我不少时间,大部分时间 花费在 调试 内存问题上。

例如在销毁十字链表时,多次释放节点空间,造成 _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;
}
运行截图:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息