2015年大二上-数据结构-图-1-(1)图基本算法库

图的存储结构主要包括邻接矩阵和邻接表,本算法库提供存储结构的定义,以及用于构造图存储结构、不同结构的转换及显示的代码。算法库采用程序的多文件组织形式,包括两个文件:

  

  1.头文件:Graph.h,包含定义图数据结构的代码、宏定义、要实现算法的函数的声明;

/*  
*Copyright (c) 2014,烟台大学计算机学院  
*All rights reserved.  
*文件名称:Annpion.cpp  
*作者:王耀鹏  
*完成日期:2016年1月23日  
*版本号:v1.0  
*  
*问题描述:图基本算法库
*输入描述:无  
*输出描述:图的基本操作
*/  
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED

#define MAXV 100                //最大顶点个数
#define INF 32767       //INF表示∞
typedef int InfoType;

//以下定义邻接矩阵类型
typedef struct
{
    int no;                     //顶点编号
    InfoType info;              //顶点其他信息,在此存放带权图权值
} VertexType;                   //顶点类型

typedef struct                  //图的定义
{
    int edges[MAXV][MAXV];      //邻接矩阵
    int n,e;                    //顶点数,弧数
    VertexType vexs[MAXV];      //存放顶点信息
} MGraph;                       //图的邻接矩阵类型

//以下定义邻接表类型
typedef struct ANode            //弧的结点结构类型
{
    int adjvex;                 //该弧的终点位置
    struct ANode *nextarc;      //指向下一条弧的指针
    InfoType info;              //该弧的相关信息,这里用于存放权值
} ArcNode;

typedef int Vertex;

typedef struct Vnode            //邻接表头结点的类型
{
    Vertex data;                //顶点信息
    int count;                  //存放顶点入度,只在拓扑排序中用
    ArcNode *firstarc;          //指向第一条弧
} VNode;

typedef VNode AdjList[MAXV];    //AdjList是邻接表类型

typedef struct
{
    AdjList adjlist;            //邻接表
    int n,e;                    //图中顶点数n和边数e
} ALGraph;                      //图的邻接表类型

//功能:由一个反映图中顶点邻接关系的二维数组,构造出用邻接矩阵存储的图
//参数:Arr - 数组名,由于形式参数为二维数组时必须给出每行的元素个数,在此将参数Arr声明为一维数组名(指向int的指针)
//      n - 矩阵的阶数
//      g - 要构造出来的邻接矩阵数据结构
void ArrayToMat(int *Arr, int n, MGraph &g); //用普通数组构造图的邻接矩阵
void ArrayToList(int *Arr, int n, ALGraph *&G); //用普通数组构造图的邻接表
void MatToList(MGraph g,ALGraph *&G);//将邻接矩阵g转换成邻接表G
void ListToMat(ALGraph *G,MGraph &g);//将邻接表G转换成邻接矩阵g
void DispMat(MGraph g);//输出邻接矩阵g
void DispAdj(ALGraph *G);//输出邻接表G

#endif // GRAPH_H_INCLUDED

  2.源文件:Graph.cpp,包含实现各种算法的函数的定义

/*  
*Copyright (c) 2014,烟台大学计算机学院  
*All rights reserved.  
*文件名称:Annpion.cpp  
*作者:王耀鹏  
*完成日期:2016年1月23日  
*版本号:v1.0  
*  
*问题描述:图基本算法库
*输入描述:无  
*输出描述:图的基本操作
*/  
#include <stdio.h>
#include <malloc.h>
#include "Graph.h"
//功能:由一个反映图中顶点邻接关系的二维数组,构造出用邻接矩阵存储的图
//参数:Arr - 数组名,由于形式参数为二维数组时必须给出每行的元素个数,在此将参数Arr声明为一维数组名(指向int的指针)
//      n - 矩阵的阶数
//      g - 要构造出来的邻接矩阵数据结构
void ArrayToMat(int *Arr, int n, MGraph &g) //用普通数组构造图的邻接矩阵
{
    int i,j,count=0;                        //count用于统计边数,即矩阵中非0元素个数
    g.n=n;
    for(i=0; i<n; ++i)
        for(j=0; j<n; ++j)
        {
            g.edges[i][j]=Arr[i*n+j];          //将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j]
            if(g.edges[i][j]!=0&&g.edges[i][j]!=INF)
                ++count;
        }
    g.e=count;
}
void ArrayToList(int *Arr, int n, ALGraph *&G) //用普通数组构造图的邻接表
{
    int i,j,count=0;                           //count用于统计边数,即矩阵中非0元素个数
    ArcNode *p;
    G=(ALGraph *)malloc(sizeof(ALGraph));
    G->n=n;
    for(i=0; i<n; ++i)
        G->adjlist[i].firstarc=NULL;
    for(i=0; i<n; ++i)
        for(j=n-1; j>=0; --j)
            if(Arr[i*n+j]!=0)
            {
                p=(ArcNode *)malloc(sizeof(ArcNode));
                p->adjvex=j;
                p->info=Arr[i*n+j];
                p->nextarc=G->adjlist[i].firstarc;
                G->adjlist[i].firstarc=p;
                ++count;
            }
    G->e=count;
}
void MatToList(MGraph g,ALGraph *&G)//将邻接矩阵g转换成邻接表G
{
    int i,j;
    G=(ALGraph *)malloc(sizeof(ALGraph));
    ArcNode *p;
    G->n=g.n;
    G->e=g.e;
    for(i=0; i<g.n; ++i)
        G->adjlist[i].firstarc=NULL;
    for(i=0; i<g.n; ++i)
        for(j=g.n-1; j>=0; --j)
            if(g.edges[i][j]!=0)
            {
                p=(ArcNode *)malloc(sizeof(ArcNode));
                p->adjvex=j;
                p->info=g.edges[i][j];
                p->nextarc=G->adjlist[i].firstarc;
                G->adjlist[i].firstarc=p;
            }
}
void ListToMat(ALGraph *G,MGraph &g)//将邻接表G转换成邻接矩阵g
{
    int i,j;
    ArcNode *p;
    g.n=G->n;
    g.e=G->e;
    for(i=0; i<G->n; ++i)
        for(j=0; j<G->n; ++j)
            g.edges[i][j]=0;
    for(i=0; i<G->n; ++i)
    {
        p=G->adjlist[i].firstarc;
        while(p!=NULL)
        {
            g.edges[i][p->adjvex]=p->info;
            p=p->nextarc;
        }
    }
}
void DispMat(MGraph g)//输出邻接矩阵g
{
    int i,j;
    for(i=0; i<g.n; ++i)
    {
        for(j=0; j<g.n; ++j)
        {
            if (g.edges[i][j]==INF)
                printf("%3s","∞");
            else
                printf("%3d",g.edges[i][j]);
        }
        printf("\n");
    }
}
void DispAdj(ALGraph *G)//输出邻接表G
{
    int i;
    ArcNode *p;
    for (i=0; i<G->n; i++)
    {
        p=G->adjlist[i].firstarc;
        printf("%3d: ",i);
        while (p!=NULL)
        {
            printf("-->%d/%d ",p->adjvex,p->info);
            p=p->nextarc;
        }
        printf("\n");
    }
}

3.在同一项目(project)中建立一个源文件(如main.cpp),编制main函数,完成相关的测试工作。 例:

/*  
*Copyright (c) 2014,烟台大学计算机学院  
*All rights reserved.  
*文件名称:Annpion.cpp  
*作者:王耀鹏  
*完成日期:2016年1月23日  
*版本号:v1.0  
*  
*问题描述:图基本算法库
*输入描述:无  
*输出描述:图的基本操作
*/  
#include <stdio.h>
#include <malloc.h>
#include "graph.h"

int main()
{
    MGraph g1,g2;
    ALGraph *G1,*G2;
    int A[6][6]=
    {
        {0,5,0,7,0,0},
        {0,0,4,0,0,0},
        {8,0,0,0,0,9},
        {0,0,5,0,0,6},
        {0,0,0,5,0,0},
        {3,0,0,0,1,0}
    };

    ArrayToMat(A[0], 6, g1);  //取二维数组的起始地址作实参,用A[0],因其实质为一维数组地址,与形参匹配
    printf(" 有向图g1的邻接矩阵:\n");
    DispMat(g1);

    ArrayToList(A[0], 6, G1);
    printf(" 有向图G1的邻接表:\n");
    DispAdj(G1);

    MatToList(g1,G2);
    printf(" 图g1的邻接矩阵转换成邻接表G2:\n");
    DispAdj(G2);

    ListToMat(G1,g2);
    printf(" 图G1的邻接表转换成邻接邻阵g2:\n");
    DispMat(g2);
    printf("\n");
    return 0;
}

运行结果:



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面我来介绍一下如何在RT-Thread自行设计哈希算法实现加密功能。具体实现过程如下: 1. 选择合适的哈希算法。哈希算法的设计需要考虑安全性和效率等因素。目前常用的哈希算法有MD5、SHA1、SHA256等,可以选择其一个作为基础算法进行设计。 2. 实现哈希算法的核心函数。哈希算法的核心函数是将输入数据转换为哈希值的函数,需要根据具体算法进行设计。以SHA256算法为例,其核心函数可以参考以下代码: ```c void sha256_core(const unsigned char *input, int len, unsigned int *hash) { unsigned int w[64], a, b, c, d, e, f, g, h, t1, t2; int i; // 初始化哈希值 hash[0] = 0x6a09e667; hash[1] = 0xbb67ae85; hash[2] = 0x3c6ef372; hash[3] = 0xa54ff53a; hash[4] = 0x510e527f; hash[5] = 0x9b05688c; hash[6] = 0x1f83d9ab; hash[7] = 0x5be0cd19; // 分组处理输入数据 for (i = 0; i < len / 64; i++) { // 将输入数据分为16个32位的字 for (int j = 0; j < 16; j++) { w[j] = (input[i * 64 + j * 4] << 24) | (input[i * 64 + j * 4 + 1] << 16) | (input[i * 64 + j * 4 + 2] << 8) | (input[i * 64 + j * 4 + 3]); } // 扩展16个字为64个字 for (int j = 16; j < 64; j++) { w[j] = SIG1(w[j - 2]) + w[j - 7] + SIG0(w[j - 15]) + w[j - 16]; } // 初始化变量 a = hash[0]; b = hash[1]; c = hash[2]; d = hash[3]; e = hash[4]; f = hash[5]; g = hash[6]; h = hash[7]; // 压缩函数 for (int j = 0; j < 64; j++) { t1 = h + EP1(e) + CH(e, f, g) + K[j] + w[j]; t2 = EP0(a) + MAJ(a, b, c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; } // 更新哈希值 hash[0] += a; hash[1] += b; hash[2] += c; hash[3] += d; hash[4] += e; hash[5] += f; hash[6] += g; hash[7] += h; } } ``` 其,EP0、EP1、SIG0、SIG1、CH、MAJ和K等宏定义可以在SHA256算法的标准找到。 3. 实现哈希算法的输入数据处理函数。哈希算法的输入数据需要进行填充和长度扩展等处理,以满足算法的要求。以SHA256算法为例,其输入数据处理函数可以参考以下代码: ```c void sha256_input(const unsigned char *input, int len, unsigned char *output) { unsigned char block[64]; unsigned int hash[8]; int i; // 填充输入数据 for (i = 0; i < len / 64; i++) { memcpy(block, input + i * 64, 64); sha256_core(block, 64, hash); } // 填充最后一个块 int last_block_len = len % 64; memcpy(block, input + i * 64, last_block_len); block[last_block_len] = 0x80; if (last_block_len >= 56) { sha256_core(block, 64, hash); memset(block, 0, 64); } *(unsigned long long *)(block + 56) = len * 8; sha256_core(block, 64, hash); // 输出哈希值 for (i = 0; i < 8; i++) { output[i * 4] = hash[i] >> 24; output[i * 4 + 1] = hash[i] >> 16; output[i * 4 + 2] = hash[i] >> 8; output[i * 4 + 3] = hash[i]; } } ``` 其,填充规则和补位规则可以在SHA256算法的标准找到。 4. 将计算得到的哈希值用于加密。例如,在密码验证时,可以将用户输入的密码计算哈希值后与预先存储的哈希值进行比较,从而实现密码验证功能。 需要注意的是,在使用自行设计的哈希算法进行加密时,需要进行充分的测试和评估,以确保算法的正确性和安全性。同时,还需要注意密码哈希值的存储和传输安全,避免被攻击者窃取。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值