zoukankan      html  css  js  c++  java
  • 看数据结构写代码(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("--------------------遍历開始-----------------
    ");
    	for (int i = 0; i < list.rowNum; i++)
    	{
    		MatrixNode * next = list.rowHead[i]->rightNext;
    		while (next != NULL)
    		{
    			printf("%d行 %d列 : %d
    ",next->row+1,next->col+1,next->data);
    			next = next->rightNext;
    		}
    	}
    	printf("--------------------遍历结束------------------
    ");
    }
    
    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------------
    ");
    	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------------
    ");
    	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------------
    ");
    	listAdd(&list1,list2);
    	listTraverse(list1);
    	printf("--------------------矩阵1 = 矩阵1 - 矩阵2------------
    ");
    	listSub(&list1,list2);
    	listTraverse(list1);
    	printf("--------------------矩阵3------------
    ");
    	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------------
    ");
    	CrossList list4;
    	listMult(list1,list3,&list4);
    	listTraverse(list4);
    	//释放内存空间
    	listDestory(&list1);
    	listDestory(&list2);
    	listDestory(&list3);
    	listDestory(&list4);
    	return 0;
    }
    
    执行截图:






  • 相关阅读:
    js表单提交回调函数
    sublime text3下BracketHighlighter的配置方法
    不同版本的jquery的复选框checkbox的相关问题
    jquery键盘常见事件
    jQuery学习笔记(一)
    sublime text按esc经常进入command mode(不能输入任何东西)
    sublime text光标移入移出括号的快捷键设置
    sublime text3 自己定义的不同浏览器的预览快捷键
    grains和pillar的联合使用
    自定义模块和grains
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6931809.html
Copyright © 2011-2022 走看看