第十二周项目2-操作用临界表存储的图

本文介绍了一种使用邻接表存储结构实现图算法的方法,包括输出顶点出度、找出最大出度顶点、计算出度为0的顶点数量及判断边的存在性,并通过具体示例展示了算法的实现过程。

问题及代码:

/*     
*烟台大学计算机与控制工程学院      
*作    者:张相如 
*完成日期:2016年11月17日  
*问题描述:假设图G采用邻接表存储,分别设计实现以下要求的算法:    
(1)输出出图G中每个顶点的出度;    
(2)求出图G中出度最大的一个顶点,输出该顶点编号;    
(3)计算图G中出度为0的顶点数;    
(4)判断图G中是否存在边<i,j> 。    
利用下图作为测试用图,输出结果。    
 
提示:(1)分别设计函数实现算法;(2)不要全部实现完再测试,而是实现一个,测试一个;(3)请利用图算法库。     
  
  
*/  

graph.h:

#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 *&); //用普通数组构造图的邻接表  
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  

graph.cpp:

#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<g.n; i++)    
        for (j=0; j<g.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)    
                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)      //存在一条边,将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j]    
            {    
                p=(ArcNode *)malloc(sizeof(ArcNode));   //创建一个节点*p    
                p->adjvex=j;    
                p->info=Arr[i*n+j];    
                p->nextarc=G->adjlist[i].firstarc;      //采用头插法插入*p    
                G->adjlist[i].firstarc=p;    
            }    
    
    G->e=count;    
}    
    
    
void MatToList(MGraph g,ALGraph *&G)//将邻接矩阵g转换成邻接表G    
{    
    int i,j;    
    ArcNode *p;    
    G=(ALGraph *)malloc(sizeof(ALGraph));    
    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    
                p->adjvex=j;    
                p->info=g.edges[i][j];    
                p->nextarc=G->adjlist[i].firstarc;      //采用头插法插入*p    
                G->adjlist[i].firstarc=p;    
            }    
    G->n=g.n;    
    G->e=g.e;    
}    
    
    
void ListToMat(ALGraph *G,MGraph &g)//将邻接表G转换成邻接矩阵g    
{    
    int i,j;    
    ArcNode *p;    
    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;    
        }    
    }    
    g.n=G->n;    
    g.e=G->e;    
}    
    
    
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");    
    }    
}    
//返回图G中编号为v的顶点的出度    
int OutDegree(ALGraph *G,int v)    
{    
    ArcNode *p;    
    int n=0;    
    p=G->adjlist[v].firstarc;    
    while (p!=NULL)    
    {    
        n++;    
        p=p->nextarc;    
    }    
    return n;    
}    
//输出图G中每个顶点的出度    
void OutDs(ALGraph *G)    
{    
    int i;    
    for (i=0; i<G->n; i++)    
        printf("  顶点%d:%d\n",i,OutDegree(G,i));    
}    
    
    
//输出图G中出度最大的一个顶点    
void OutMaxDs(ALGraph *G)    
{    
    int maxv=0,maxds=0,i,x;    
    for (i=0; i<G->n; i++)    
    {    
        x=OutDegree(G,i);    
        if (x>maxds)    
        {    
            maxds=x;    
            maxv=i;    
        }    
    }    
    printf("顶点%d,出度=%d\n",maxv,maxds);    
}    
//输出图G中出度为0的顶点数    
void ZeroDs(ALGraph *G)    
{    
    int i,x;    
    for (i=0; i<G->n; i++)    
    {    
        x=OutDegree(G,i);    
        if (x==0)    
            printf("%2d",i);    
    }    
    printf("\n");    
}    
    
//返回图G中是否存在边<i,j>    
bool Arc(ALGraph *G, int i,int j)    
{    
    ArcNode *p;    
    bool found = false;    
    p=G->adjlist[i].firstarc;    
    while (p!=NULL)    
    {    
        if(p->adjvex==j)    
        {    
            found = true;    
            break;    
        }    
        p=p->nextarc;    
    }    
    return found;    
}    

main.cpp:

#include<stdio.h>    
#include<malloc.h>    
#include"graph.h"    
int main()    
{    
    ALGraph *G;    
    int A[7][7]=    
    {    
        {0,1,1,1,0,0,0},    
        {0,0,0,0,1,0,0},    
        {0,0,0,0,1,1,0},    
        {0,0,0,0,0,0,1},    
        {0,0,0,0,0,0,0},    
        {0,0,0,1,1,0,1},    
        {0,1,0,0,0,0,0}    
    };    
    ArrayToList(A[0], 7, G);    
    printf("(1)各顶点出度:\n");    
    OutDs(G);    
    printf("(2)最大出度的顶点信息:");    
    OutMaxDs(G);    
    printf("(3)出度为0的顶点:");    
    ZeroDs(G);    
    printf("(4)边<2,6>存在吗?");    
    if(Arc(G,2,6))    
        printf("是\n");    
    else    
        printf("否\n");    
    printf("\n");    
    return 0;    
}

运行结果:


知识点总结:学习操作永邻接表存储的图

下载前可以先看下教程 https://pan.quark.cn/s/16a53f4bd595 小天才电话手刷机教程 — 基础篇 我们将为您简单的介绍小天才电话手新机型的简单刷机以及玩法,如adb工具的使用,magisk的刷入等等。 我们会确保您看完此教程后能够对Android系统有一个最基本的认识,以及能够成功通过magisk root您的手,并安装您需要的第三方软件。 ADB Android Debug Bridge,简称,在android developer的adb文档中是这么描述它的: 是一种多功能命令行工具,可让您与设备进行通信。 该命令有助于各种设备操作,例如安装和调试应用程序。 提供对 Unix shell 的访问,您可以使用它在设备上运行各种命令。 它是一个客户端-服务器程序。 这听起来有些难以理解,因为您也没有必要去理解它,如果您对本文中的任何关键名词产生疑惑或兴趣,您都可以在搜索引擎中去搜索它,当然,我们会对其进行简单的解释:是一款在命令行中运行的,用于对Android设备进行调试的工具,并拥有比一般用户以及程序更高的权限,所以,我们可以使用它对Android设备进行最基本的调试操作。 而在小天才电话手上启用它,您只需要这么做: - 打开拨号盘; - 输入; - 点按打开adb调试选项。 其次是电脑上的Android SDK Platform-Tools的安装,此工具是 Android SDK 的组件。 它包括与 Android 平台交互的工具,主要由和构成,如果您接触过Android开发,必然会使用到它,因为它包含在Android Studio等IDE中,当然,您可以独立下载,在下方选择对应的版本即可: - Download SDK Platform...
<think>嗯,用户问的是C语言中如何求临界值的末八位二进制位。首先,我需要明确“临界值”在这里具体指的是什么。可能是指某个特定条件下的数值,比如整数溢出的临界点,或者某个算法中的关键阈值。不过,用户没有具体说明,可能需要做一些假设。假设这里的临界值是指当某个变量达到其数据类型所能示的最大值之前的一个值,比如对于32位整数来说,临界值可能是2147483647,这时候求它的末八位二进制。 接下来,用户需要的是将这个临界值转换为二进制,并取最后八位。在C语言中,处理二进制末八位通常可以使用位操作,特别是按位与运算符(&)。因为取末八位二进制相当于取数值对256(即2的8次方)的余数,或者用位运算的话,就是和0xFF(二进制11111111)进行按位与操作。这样高位会被清零,只保留最后八位。 然后,需要考虑临界值的数据类型。如果是int类型,通常为32位或16位,取决于系统。但现代系统中int通常是32位的。如果是unsigned int,处理方式类似。但要注意溢出问题,比如当临界值本身就是最大值时,比如0xFFFFFFFF(32位无符号整型的最大值),取末八位的话就是0xFF。这时候用value & 0xFF就能得到。 不过,用户可能遇到的场景可能更复杂,比如处理有符号整数的情况。这时候需要注意符号位的影响。例如,对于有符号的char类型,最高位是符号位,但如果是用更大的数据类型(如int),取最后八位的话,可能包括符号位的扩展。但用户可能只需要纯粹的二进制末八位,不考虑符号,所以应该使用无符号类型或者确保位操作的正确性。 此外,还需要考虑如何将结果输出为二进制字符串,方便查看。C语言标准库中没有直接输出二进制的函数,所以需要手动实现,比如通过位移和掩码操作逐位获取每一位的值,然后存储到字符串中,或者直接打印出来。 可能的步骤总结如下: 1. 确定临界值的具体数值,比如数据类型的最大值减一。 2. 使用位操作(& 0xFF)获取末八位。 3. 将结果转换为二进制字符串示。 举个例子,如果临界值是2147483647(即0x7FFFFFFF),那么末八位是0xFF(二进制的11111111),但实际计算时,2147483647 & 0xFF的结果是0xFF吗?是的,因为0x7FFFFFFF的十六进制最后两位是FF,所以按位与0xFF确实是0xFF。 另一个例子,如果临界值是255,那么末八位就是全1,即11111111。而如果是256,末八位则是00000000,因为256是0x100,末八位是00。 然后,编写C语言代码的大致流程: - 定义临界值,比如int临界值 = 2147483647; - 计算末八位:int last8 = 临界值 & 0xFF; - 将last8转换为二进制字符串显示。 在转换二进制字符串时,可以从最高位到最低位依次检查每一位是否为1。例如,从第7位到第0位,每次左移并检查。 需要注意的是,如果临界值本身是超过32位的类型,比如long long,那么同样适用,因为0xFF是八位,无论原值是多少位,按位与之后都会保留最后八位。 可能用户的问题中,临界值的来源可能是某种计算或输入,需要确保在获取临界值时没有溢出或其他错误。例如,如果临界值是通过计算得到的,比如某个循环中的计数器,当达到某个条件时的值,这时候需要确保该值正确后再进行末八位的提取。 总结来说,解决这个问题的步骤是:确定临界值的数值,使用位掩码提取末八位,然后转换为二进制形式输出。需要处理不同数据类型的可能情况,并注意符号位的影响,但使用无符号类型或适当的位操作可以避免这些问题。</think>在C语言中,求某个数值的“末八二进制位”,通常指提取该数值二进制示的最后8位(即最低有效位)。以下是分步解释和示例代码: --- ### **1. 核心思路** - **位运算原理**:通过**按位与(&)**运算,将数值与掩码`0xFF`(二进制`11111111`)进行运算,保留最后8位,其余位清零。 - **数学等价**:等同于计算数值对`256`(即`2^8`)取余。 --- ### **2. 具体步骤** #### **(1) 定义临界值** 假设临界值为`int`类型的变量: ```c int critical_value = 12345; // 示例值,可替换为实际临界值 ``` #### **(2) 提取末八位** ```c int last_8_bits = critical_value & 0xFF; ``` - **解释**:`0xFF`是十六进制掩码,对应二进制`11111111`,运算后仅保留原数值的最后8位。 --- ### **3. 转换为二进制字符串(可选)** 若需直观显示二进制形式,可编写函数将`last_8_bits`转换为8位二进制字符串: ```c void to_binary(int num, char* buffer) { for (int i = 7; i >= 0; i--) { buffer[7 - i] = (num & (1 << i)) ? '1' : '0'; } buffer[8] = '\0'; // 字符串结束符 } // 使用示例 char bin_str[9]; to_binary(last_8_bits, bin_str); printf("末八位二进制: %s\n", bin_str); ``` --- ### **4. 完整代码示例** ```c #include <stdio.h> void to_binary(int num, char* buffer) { for (int i = 7; i >= 0; i--) { buffer[7 - i] = (num & (1 << i)) ? '1' : '0'; } buffer[8] = '\0'; } int main() { int critical_value = 12345; // 示例临界值 int last_8_bits = critical_value & 0xFF; char bin_str[9]; to_binary(last_8_bits, bin_str); printf("临界值十进制: %d\n", critical_value); printf("末八位十进制: %d\n", last_8_bits); printf("末八位二进制: %s\n", bin_str); return 0; } ``` --- ### **5. 运行结果** ``` 临界值十进制: 12345 末八位十进制: 57 末八位二进制: 00111001 ``` --- ### **6. 关键点** - **掩码选择**:`0xFF`适用于32位或64位整数;若处理更短类型(如`char`),需调整掩码。 - **负数处理**:若临界值为负数,直接使用`& 0xFF`会保留补码形式的最后8位。如需无符号结果,可强制转换为`unsigned char`。 希望以上内容能帮助你理解如何在C语言中提取数值的末八二进制位!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值