| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 6271 人关注过本帖, 2 人收藏
标题:华山论剑 之 [矩阵]
只看楼主 加入收藏
demonleer
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:10
帖 子:483
专家分:1225
注 册:2012-6-4
收藏
得分:0 
以下是引用有容就大在2012-8-11 14:03:06的发言:

俺在看 写的很好啊  。。。


哈哈,荣幸之至。
2012-08-11 14:24
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
致小施
matrix_set中value为0还是有问题。因为你行首也是用的链表,当该行仅包含一个元素时,删除该元素后应该将这个行结点也删除掉,对吧?你的代码中好像没有处理这种情况。


重剑无锋,大巧不工
2012-08-11 15:44
demonleer
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:10
帖 子:483
专家分:1225
注 册:2012-6-4
收藏
得分:0 
以下是引用beyondyf在2012-8-11 15:44:25的发言:

致小施
matrix_set中value为0还是有问题。因为你行首也是用的链表,当该行仅包含一个元素时,删除该元素后应该将这个行结点也删除掉,对吧?你的代码中好像没有处理这种情况。


哈哈,确实确实,粗心大意的毛病什么时候才能改了,哎。

在那个if里加上这样两句应该就可以了:

*target = current->next;
free(current);
2012-08-11 15:59
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
以下是引用demonleer在2012-8-11 15:59:14的发言:

 
 
哈哈,确实确实,粗心大意的毛病什么时候才能改了,哎。
 
在那个if里加上这样两句应该就可以了:
 
*target = current->next;
free(current);
*target = current->down;?

梅尚程荀
马谭杨奚







                                                       
2012-08-11 16:09
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
致小施
之后的运算函数逻辑上倒没什么问题,只是运算效率太低了。
虽然调用已有的get和set函数可以简化代码,但每操作一个元素都要重新定位一次。
设矩阵尺寸为n行m列,则每次定位的时间复杂度中O(n+m)。以加法运算为例,每一次矩阵加法运算的时间复杂度是O(n*m*(n+m))。如果认为n接近于m,则可以表达成O(n^3)。
事实利用稀疏的特点,设矩阵中有效元素的数量为c,则两个矩阵相加的时间复杂度可以达到O(c)的程度。相差3个数量级,这一定要引起重视。
这有多大差别?如果O(c)的算法需要计算1秒钟的话,O(n^3)很可能1天也算不完。

这不影响我给你的送分承诺(承诺中没有要求效率),只是我很重视程序的执行效率,希望这次论剑不光是展示各位的能力,也希望各位能有所收获。

小施的代码就看到这里,该阅读有容的代码了


[ 本帖最后由 beyondyf 于 2012-8-11 16:20 编辑 ]

重剑无锋,大巧不工
2012-08-11 16:18
demonleer
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:10
帖 子:483
专家分:1225
注 册:2012-6-4
收藏
得分:0 
以下是引用有容就大在2012-8-11 16:09:24的发言:

*target = current->down;?


蛋疼,又粗心了,应该是 *target = current->down;
2012-08-11 16:23
demonleer
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:10
帖 子:483
专家分:1225
注 册:2012-6-4
收藏
得分:0 
以下是引用beyondyf在2012-8-11 16:18:07的发言:

致小施
之后的运算函数逻辑上倒没什么问题,只是运算效率太低了。
虽然调用已有的get和set函数可以简化代码,但每操作一个元素都要重新定位一次。
设矩阵尺寸为n行m列,则每次定位的时间复杂度中O(n+m)。以加法运算为例,每一次矩阵加法运算的时间复杂度是O(n*m*(n+m))。如果认为n接近于m,则可以表达成O(n^3)。
事实利用稀疏的特点,设矩阵中有效元素的数量为c,则两个矩阵相加的时间复杂度可以达到O(c)的程度。相差3个数量级,这一定要引起重视。
这有多大差别?如果O(c)的算法需要计算1秒钟的话,O(n^3)很可能1天也算不完。

这不影响我给你的送分承诺(承诺中没有要求效率),只是我很重视程序的执行效率,希望这次论剑不光是展示各位的能力,也希望各位能有所收获。

小施的代码就看到这里,该阅读有容的代码了


效率确实是个问题,我看看能不能改进,多谢杨大哥指点。

拜谢。
2012-08-11 16:26
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
致有容
Matrix_set没有对0值的处理,这将使你固定的矩阵空间很快被本不该出现的0消耗掉。
矩阵的存储方式实在不是三元组行链的实现方式,这点我很报歉,要尽快修改。你这种方式受限太多,几乎不实用,而且操作复杂度更高。

重剑无锋,大巧不工
2012-08-11 17:23
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
回复 58楼 beyondyf
呵呵 正在修改中……

梅尚程荀
马谭杨奚







                                                       
2012-08-11 17:29
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
搞了大半天 终于搞定了 发上来杨大哥帮看看
这个算不算一个带行逻辑链信息的表示方式? 每行有头头结点保存该行的非零元个数
这样遍历下行数组就能知道矩阵的稠密度了吧。
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define  MAX_ROW  1000  // 矩阵的最大行数
#define     MAX_COL  1000  // 矩阵的最大列数
typedef  int status;
typedef  double  elem_type;

typedef struct node
{
    elem_type  data;    // 结点非零元的值
    int  column;        // 结点的列数
    struct node  *next; // 指向下一结点的指针

}node;

typedef struct head
{
    int row;  //  头结点的行数
    int sum;  //  此行拥有的非零元的个数
    struct node *right; // 此行的非零结点的指针
}head;

typedef struct matrix
{
    head  head_array[MAX_ROW]; // 头结点数组
    int   m_row , m_col;        // 矩阵的实际行数 和 列数
}MATRIX;


//////////////////////////////////
// 子函数声明
//////////////////////////////////
MATRIX * Matrix_create(int row, int column);     // 创建rows行columns列矩阵,元素初始值为0
void Matrix_free(MATRIX * mat);                  // 销毁mat矩阵
status  Matrix_rows_len(MATRIX * mat);           // 获取矩阵mat的行数,mat为空指针时返回0
status  Matrix_cols_len(MATRIX * mat);           // 获取矩阵mat的列数,mat为空指针时返回0
status  Matrix_set(MATRIX * mat, int row,
               int column, double value);        // 设置mat矩阵第row行第column列的元素值为value,
                                                 // 操作成功返回0值,否则返回非0
                                                 // 其实相当于插入操作
void Matrix_print(MATRIX *mat);                  // 以稀疏矩阵的形式输出
elem_type Matrix_get(MATRIX * mat, int row,      // 获取mat矩阵第row行第column列的元素值
                  int column);           

MATRIX * Matrix_add(MATRIX * mat1,               // 计算两个矩阵相加,返回和矩阵。当两个矩阵不
                    MATRIX * mat2);              // 能作加法运算时返回NULL
MATRIX * Matrix_trans(MATRIX * mat);             // 返回mat的转置矩阵
MATRIX * Matrix_mul_real(MATRIX * mat,           // 计算矩阵与实数相乘
                         double a);
MATRIX * Matrix_dot_mul(MATRIX * mat1,           //计算两个矩阵的点乘。如果不能作运算返回NULL
                        MATRIX * mat2);
MATRIX * Matrix_mul(MATRIX * mat1,              // 计算两个矩阵相乘,注意是mat1左乘mat2。
                    MATRIX * mat2);             // 如果不能作乘法运算返回NULL


//////////////////////////////////
// 主函数入口
//////////////////////////////////
int  main(void)
{
    MATRIX *mat1, *mat2, *mat_trans;
    MATRIX *mat_add, *mat_dot, *mat_mul;

    // create
    mat1 = Matrix_create(5, 5);
    mat2 = Matrix_create(5, 5);

    //set
    Matrix_set(mat1, 2, 3, 5);
    Matrix_set(mat1, 1, 4, 9);
    Matrix_set(mat1, 3, 1, 9);
    Matrix_set(mat1, 3, 1, 0);
    Matrix_set(mat1, 5, 4, 7);
    Matrix_set(mat2, 2, 4, 8);
    Matrix_set(mat2, 3, 2, 3);
    Matrix_set(mat2, 5, 4, 6);
  

    printf("Original!\n");
    Matrix_print(mat1);
    Matrix_print(mat2);

    printf("Add!\n");
    mat_add = Matrix_add(mat1,  mat2);
    Matrix_print(mat_add);

    printf("Trans!\n");
    mat_trans = Matrix_trans(mat2);
    Matrix_print(mat_trans);

    printf("real_mul!\n");
    Matrix_mul_real(mat1, 3);
    Matrix_print(mat1);

    printf("Dot_mul!\n");
    mat_dot = Matrix_dot_mul(mat1, mat2);
    Matrix_print(mat_dot);

    printf("Multiply!\n");
    mat_mul = Matrix_mul(mat1,  mat2);
    Matrix_print(mat_mul);  


    Matrix_free(mat1);
    Matrix_free(mat2);
    Matrix_free(mat_add);
    Matrix_free(mat_trans);
    Matrix_free(mat_dot);
    Matrix_free(mat_mul);

    system("pause");
    return 0;
}

//////////////////////////////////
// 各个子函数的具体实现
//////////////////////////////////

MATRIX * Matrix_create(int row, int column)
{
    MATRIX *mat;
    int i;
    node *p;
    mat = (MATRIX *) malloc (sizeof (MATRIX));
    mat->m_row = row;
    mat->m_col = column;
    for (i = 1; i <= mat->m_row; i++)
    {
        p = (node *)malloc(sizeof(node));       // 每行头结点包含一个node结点

        mat->head_array[i].right = p;           // 使头结点与开辟的结点联系起来
        mat->head_array[i].row = i;             // 头结点行数
        mat->head_array[i].sum = 0;             // 头结点保存的初始非零元个数
        mat->head_array[i].right->column = 0;   // 设置头结点的列数为0
        mat->head_array[i].right->data = 0;     // 设置头结点的data数据为0
        mat->head_array[i].right->next = NULL;  // 初始化next为NULL
    }

    return mat;
}

//-----------------------------------------
void Matrix_print(MATRIX *mat)
{
    int i, j;
    node *p;
    for (i = 1; i <= mat->m_row; i++)
    {
        p = mat->head_array[i].right->next;  // 指向每行的第一个结点
        if (0 == mat->head_array[i].sum) 

        {
            for (j = 1; j <= mat->m_col; j++)
                printf("%-5.1f", 0);       

        }
        else{

                 for (j = 1; j <= mat->m_col; j++)
                {
                    if (NULL != p && p->column == j)
                    {
                        printf("%-5.1f", p->data);
                        p = p->next;
                    }
                    else printf("%-5.1f", 0);                                   

                }       

             }
       printf("\n");
    }
    printf("\n");
}

//-------------------------------------------
void Matrix_free(MATRIX * mat)
{
    int i;
    node *p, *q;
    if (NULL == mat) return ;
    for (i = 1; i <= mat->m_row; i++)
    {
        p = mat->head_array[i].right;               

        while (p != NULL)
        {
            q = p;
            p = p->next;
            free(q);
        }
    }
    free(mat);
}

//----------------------------------------------
status  Matrix_rows_len(MATRIX * mat)           // 获取矩阵mat的行数,mat为空指针时返回0
{
    if (NULL == mat)
        return 0;
    else

        return mat->m_row;
}

status  Matrix_cols_len(MATRIX * mat)           // 获取矩阵mat的列数,mat为空指针时返回0
{
    if (NULL == mat)
        return 0;
    else

        return mat->m_col;
}

//------------------------------------------------
elem_type Matrix_get(MATRIX * mat, int row,      // 获取mat矩阵第row行第column列的元素值
                  int column)
{
    node *p = mat->head_array[row].right;
    while (p->column =! column) p = p->next;
    return p->data;
}

//-------------------------------------------------
status  Matrix_set(MATRIX * mat, int row,
               int column, double value)         // 设置mat矩阵第row行第column列的元素值为value,
                                                 // 操作成功返回0值,否则返回非0
{
    node *p;
    node *q, *insert;
    if (row > mat->m_row || column > mat->m_col || row < 1 || column < 1)
    {
        printf("Beyond now!\n");
        return -1;
    }
    p = mat->head_array[row].right;
    while (NULL != p && p->column < column)  // 寻找适当的位置
        {
            q = p;
            p = p->next;
        }
    if (NULL == p)    // 原来的行中没有非零元 或者插入的元在行的最后
    {
        insert = (node *)malloc(sizeof(node));
        insert->data = value;
        insert->next = NULL;
        insert->column = column;
        q->next = insert;                       

        mat->head_array[row].sum += 1;
        return 0;
    }       

    if (NULL != p && p->column == column && value == 0)   // 在链中找到一个非零元和要求的位置一样
    {                                             // 并且value = 0
        q->next = p->next;
        free(p);
        mat->head_array[row].sum -= 1;            // 行的非零元数量减一
        return 0;
    }
    if (NULL != p && p->column == column && value != 0)    // value != 0
    {
        p->data = value;
        return 0;
    }
    if (NULL != p && p->column != column && value != 0)   // 在链中间插入一个新的非零元
    {
        insert = (node *)malloc(sizeof(node));
        q->next = insert;       

        insert->next = p;
        insert->column = column;
        insert->data = value;
        mat->head_array[row].sum += 1;
        return 0;
    }
    return -1;
}

//------------------------------------------------
MATRIX * Matrix_add(MATRIX * mat1,               // 计算两个矩阵相加,返回和矩阵。当两个矩阵不
                    MATRIX * mat2)               // 能作加法运算时返回NULL
{
    int i;
    MATRIX *mat3 = Matrix_create(mat1->m_col, mat1->m_row);
   

    node *p, *q;
    if (mat1->m_col == mat2->m_col && mat1->m_row == mat2->m_row)
    {       

        for (i = 1; i <= mat1->m_row; i++)
        {
            p = mat1->head_array[i].right->next;
            q = mat2->head_array[i].right->next;
            while (NULL != p && NULL != q)
            {
                if (p->column < q->column)
                {
                    Matrix_set(mat3, i, p->column, p->data);
                    p = p->next;
                }
                else if (p->column > q->column)
                {
                    Matrix_set(mat3, i, q->column, q->data);
                    q = q->next;
                }
                else
                {
                    Matrix_set(mat3, i, p->column, p->data + q->data);
                    p = p->next;
                    q = q->next;
                }                           

            }
            while (NULL != p)
                {
                    Matrix_set(mat3, i, p->column, p->data);
                    p = p->next;
                }
            while (NULL != q)
            {
                 Matrix_set(mat3, i, q->column, q->data);
                 q = q->next;
            }           

        }
        return mat3;
    }
    else
        return NULL;
}

//-------------------------------------
MATRIX * Matrix_trans(MATRIX * mat)             // 返回mat的转置矩阵
{
    MATRIX *mat_trans = Matrix_create(mat->m_col, mat->m_row);
    int i; node *p ;

    for (i = 1; i <= mat->m_row; i++)
    {
        p = mat->head_array[i].right->next;
        while (NULL != p)
        {
            Matrix_set(mat_trans, p->column, i, p->data);
            p = p->next;
        }
    }
    return mat_trans;
}

//----------------------------
MATRIX * Matrix_mul_real(MATRIX * mat,           // 计算矩阵与实数相乘
                         double a)
{
    int i;
    node *p;
    for (i = 1; i <= mat->m_row; i++)
    {
        p = mat->head_array[i].right->next;
        while (NULL != p)
        {
            p->data *= a;

            p = p->next;
        }
    }
    return mat;
}

//------------------------------------------
MATRIX * Matrix_dot_mul(MATRIX * mat1,           //计算两个矩阵的点乘。如果不能作运算返回NULL
                        MATRIX * mat2)
{
    MATRIX *mat_dot = Matrix_create(mat1->m_row, mat1->m_col);
    node *p, *q;
    int i;
    if (mat1->m_col == mat2->m_col && mat1->m_row == mat2->m_row)
    {
        for (i = 1; i <= mat1->m_row; i++)
        {
            p = mat1->head_array[i].right->next;
            q = mat2->head_array[i].right->next;
            while (p != NULL && q != NULL)
            {
                if (p->column < q->column)
                    p = p->next;
                else if (p->column == q->column)
                {
                    Matrix_set(mat_dot, i, q->column, q->data * p->data);
                    q = q->next;
                    p = p->next;
                }
                else if (p->column > q->column)
                    q = q->next;
            }
        }
        return mat_dot;
    }
    else

        return NULL;
}

//----------------------------------
MATRIX * Matrix_mul(MATRIX * mat1,              // 计算两个矩阵相乘,注意是mat1左乘mat2。
                    MATRIX * mat2)              // 如果不能作乘法运算返回NULL
{
    if (mat1->m_col != mat2->m_row)
        return NULL;

    MATRIX *mat_mul = Matrix_create(mat1->m_row, mat2->m_col);
    int i, j; elem_type s[MAX_COL] = {0};
    node *p, *q;
    for (i = 1; i <= mat1->m_row; i++)
    {

        for (j = 1; j <= mat2->m_col; j++)
            s[j] = 0;
        p = mat1->head_array[i].right->next;
        while (p != NULL)
        {
            q = mat2->head_array[p->column].right->next;
            while (q != NULL)
            {               

                s[q->column] += p->data * q->data;
                q = q->next;
            }
            p = p->next;
        }
        for (j = 1; j <= mat2->m_col; j++)
        {
            if (s[j] != 0)
                Matrix_set(mat_mul, i, j, s[j]);
        }
    }
    return mat_mul;
}




[ 本帖最后由 有容就大 于 2012-8-12 08:42 编辑 ]

梅尚程荀
马谭杨奚







                                                       
2012-08-12 00:01
快速回复:华山论剑 之 [矩阵]
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024212 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved