精华内容
下载资源
问答
  • 2018-08-20 11:21:43

    创建一个交换链

    本节的代码是 05-init_swapchain.cpp

    本节描述如何创建交换链,它是最终显示给用户的图像缓冲区列表。这是建立呈现所需的所有缓冲区所需的第一个步骤之一。

    这是一个关于交换链的视图,它与系统的其他部分有关。其中一些部分很常见,剩下的部分将在本节中学习。

    这里写图片描述

    Vulkan和窗口系统

    与其他图形API一样,Vulkan将窗口系统方面与核心图形API分离开来。
    在Vulkan中,窗口系统的详细信息通过WSI(窗口系统集成)扩展公开。
    您可以在使用WSI内容的Vulkan规范文档中找到这些扩展的文档。Vulkan 规范LunarG LunarXchange websiteKhronos Vulkan Registry

    WSI扩展包含对各种平台的支持。扩展被激活为一个特定的平台,通过定义:

    • VK_USE_PLATFORM_ANDROID_KHR - Android
    • VK_USE_PLATFORM_MIR_KHR - Mir
    • VK_USE_PLATFORM_WAYLAND_KHR - Wayland
    • VK_USE_PLATFORM_WIN32_KHR - Microsoft Windows
    • VK_USE_PLATFORM_XCB_KHR - X Window System, using the XCB library
    • VK_USE_PLATFORM_XLIB_KHR - X Window System, using the Xlib library

    该名称的“KHR”部分表明该符号是在Khronos扩展中定义的。

    Surface 抽象

    Vulkan使用VkSurfaceKHR对象来抽象本机平台的Surface 或窗口。这个符号定义为VK KHR表面扩展的一部分。WSI扩展中的各种函数被用来创建、操作和销毁这些Surface 对象。

    回顾实例和设备扩展

    由于您在本教程前几节中推迟了使用扩展,现在是重新回顾它们的时候了,这样您就可以激活WSI扩展,您需要使用它来与窗口系统进行交互。

    实例扩展

    为了使用WSI扩展,您需要激活通用的surface 扩展。在示例中找到 init_instance_extension_names()函数中的代码,该函数将 init_instance_extension_names()添加到加载的实例扩展列表中。

    info.instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
    

    还要注意的是,这个函数决定了特定于平台的扩展,这取决于所构建代码的平台。
    例如,如果为Windows构建的话,该函数会将VK_KHR_WIN32_SURFACE_EXTENSION_NAME
    添加到加载的实例扩展列表中。

    info.instance_extension_names.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
    

    当实例被创建时,在init_instance()函数中加载这些扩展。

    设备扩展

    交换链是一个GPU渲染图像缓冲区列表,并将其呈现给显示硬件,以便扫描输出到显示器。
    由于GPU硬件是为这些图像编写的,所以需要一个设备级的扩展来处理交换链。
    因此,样例代码将VK_KHR_SWAPCHAIN_EXTENSION_NAME的设备扩展添加到设备扩展列表中,以便加载init_device_extension_names()

    info.device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
    

    这个扩展在本节稍后将使用,用以创建交换链。

    简要概括:

    • 本示例使用init_instance_extension_names()函数来加载一般的surface扩展和特定于平台的surface扩展作为实例扩展。
    • 该示例使用init_device_extension_names()函数来加载交换链扩展作为设备扩展。

    通过访问LunarG LunarXchange website.,您可以了解更多关于实例和设备扩展的信息

    队列家族 和“呈现”

    “呈现”操作包括将一个交换链的图像放到物理显示器上,这样就可以查看它了。当应用程序想要将图像呈现给显示器时,它会使用vkQueuePresentKHR()函数将当前请求放到GPU的队列中。因此,这个函数引用的队列必须能够支持呈现请求,或者图形和呈现请求。示例如下:

    // Iterate over each queue to learn whether it supports presenting:
    VkBool32 *pSupportsPresent =
        (VkBool32 *)malloc(info.queue_family_count * sizeof(VkBool32));
    for (uint32_t i = 0; i < info.queue_family_count; i++) {
        vkGetPhysicalDeviceSurfaceSupportKHR(info.gpus[0], i, info.surface,
                                             &pSupportsPresent[i]);
    }
    
    // Search for a graphics and a present queue in the array of queue
    // families, try to find one that supports both
    info.graphics_queue_family_index = UINT32_MAX;
    info.present_queue_family_index = UINT32_MAX;
    for (uint32_t i = 0; i < info.queue_family_count; ++i) {
        if ((info.queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
            if (info.graphics_queue_family_index == UINT32_MAX)
                info.graphics_queue_family_index = i;
    
            if (pSupportsPresent[i] == VK_TRUE) {
                info.graphics_queue_family_index = i;
                info.present_queue_family_index = i;
                break;
            }
        }
    }
    
    if (info.present_queue_family_index == UINT32_MAX) {
        // If didn't find a queue that supports both graphics and present, then
        // find a separate present queue.
        for (size_t i = 0; i < info.queue_family_count; ++i)
            if (pSupportsPresent[i] == VK_TRUE) {
                info.present_queue_family_index = i;
                break;
            }
    }
    free(pSupportsPresent);
    

    这段代码重新使用了之前获得的 info.queue_family_count,因为vkGetPhysicalDeviceSurfaceSupportKHR()为每个队列家族返回一个flag。
    然后搜索一个同时支持呈现和图形的队列家族。如果没有队列家族能同时满足呈现和图形,程序会先记住支持图形的队列家族,然后再去搜索支持呈现的队列家族。
    graphics_queue_family_indexpresent_queue_family_index都被这段代码设置时,示例的后面必须使用来自graphics_queue_family_index的队列用于图形指令,以及来自present_queue_family_index的队列用于呈现。

    是的,这有点冗余,之前在“设备”章节中只进行了搜索一个支持图形的队列家族,这只是为了便于说明。一个真正的应用程序可以以不同的顺序执行这些步骤,以避免重复。

    如果没有这样的队列家族,示例程序会直接退出。

    交换链创建信息

    本节其余部分的大部分工作都是为了填充这个create info结构,用于创建交换链:

    typedef struct VkSwapchainCreateInfoKHR {
        VkStructureType                  sType;
        const void*                      pNext;
        VkSwapchainCreateFlagsKHR        flags;
        VkSurfaceKHR                     surface;
        uint32_t                         minImageCount;
        VkFormat                         imageFormat;
        VkColorSpaceKHR                  imageColorSpace;
        VkExtent2D                       imageExtent;
        uint32_t                         imageArrayLayers;
        VkImageUsageFlags                imageUsage;
        VkSharingMode                    imageSharingMode;
        uint32_t                         queueFamilyIndexCount;
        const uint32_t*                  pQueueFamilyIndices;
        VkSurfaceTransformFlagBitsKHR    preTransform;
        VkCompositeAlphaFlagBitsKHR      compositeAlpha;
        VkPresentModeKHR                 presentMode;
        VkBool32                         clipped;
        VkSwapchainKHR                   oldSwapchain;
    } VkSwapchainCreateInfoKHR;
    

    创建一个表面(Surface)

    随着WSI扩展在实例和设备中加载,您现在可以创建一个VkSurface,这样您就可以继续进行构建交换链了。您再次需要使用特定于平台的代码,出现在05-init_swapchain.cpp的顶部:

    #ifdef _WIN32
        VkWin32SurfaceCreateInfoKHR createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
        createInfo.pNext = NULL;
        createInfo.hinstance = info.connection;
        createInfo.hwnd = info.window;
        res = vkCreateWin32SurfaceKHR(info.inst, &createInfo, NULL, &info.surface);
    #endif
    

    info.connectioninfo.window 的值是在init_connection()init_window()函数中包含的更特定于平台的代码中设置的,您也可以在示例代码中找到它们。

    请注意,init_connection()init_window()函数也负责连接到显示器的特定于平台的操作,并创造实际的窗口。您刚刚用vkCreateWin32SurfaceKHR() 函数创建的VkSurfaceKHR是由Vulkan用于平台窗口对象的句柄来表示的。

    然后将生成的表面添加到交换链的create info结构:

    VkSwapchainCreateInfoKHR swapchain_ci = {};
    swapchain_ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    swapchain_ci.pNext = NULL;
    swapchain_ci.surface = info.surface;
    

    设备表面格式(Device Surface Formats)

    您还需要在创建交换链时指定表面的格式。在这种情况下,“格式”指的是VkFormat枚举所描述的像素格式,
    VK_FORMAT_B8G8R8A8_UNORM是设备表面格式的一个常见值。

    示例中的下一段代码将获得VkSurfaceFormatKHR结构的列表,其中包含由display支持的VkFormat格式,以及其他信息。因为这些示例并不关心
    显示图像和表面使用的格式,所以示例只是选择了第一个可用的格式,如果没有指定的话,就会返回到任意的、但常见的格式。

    看一看示例中的代码,它最终在create info结构中设置了格式:

    swapchain_ci.imageFormat = info.format;
    

    表面能力(Surface Capabilities)

    为了继续填充 create info 结构, 示例调用 vkGetPhysicalDeviceSurfaceCapabilitiesKHR()vkGetPhysicalDeviceSurfacePresentModesKHR() 来获得必要的信息。 然后,它可以填充以下字段:

    uint32_t desiredNumberOfSwapChainImages = surfCapabilities.minImageCount;
    
    swapchain_ci.minImageCount = desiredNumberOfSwapChainImages;
    swapchain_ci.imageExtent.width = swapChainExtent.width;
    swapchain_ci.imageExtent.height = swapChainExtent.height;
    swapchain_ci.preTransform = preTransform;
    swapchain_ci.presentMode = swapchainPresentMode;
    

    您应该将minImageCount成员设置为代表应用程序使用的缓冲策略的值,例如双缓冲或三重缓冲。这个示例查询一个交换链中可以使用的最少数量的图像,这些图像使用的是vkGetPhysicalDeviceSurfaceCapabilitiesKHR()函数,将结果存储在surfCapabilities中。要求这个最小数量的图像可以确保我们可以获得一个可呈现的图像,只要我们在试图获得另一个图像之前就展示它。这表示一个双缓冲配置,因为您将让一个图像进行渲染,而另一个图像正在呈现。如果你想要三次缓冲,那么你会要求一个更多的图像,然后在你展示它们之前,你可以获得两个缓冲。

    用于图形和当前的不同队列家族

    您在队列家族中确定了图形和呈现队列。如果它们是不同的,您需要做一些额外的工作,以允许在队列家族之间共享图像。

    swapchain_ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
    swapchain_ci.queueFamilyIndexCount = 0;
    swapchain_ci.pQueueFamilyIndices = NULL;
    uint32_t queueFamilyIndices[2] = {
        (uint32_t)info.graphics_queue_family_index,
        (uint32_t)info.present_queue_family_index};
    if (info.graphics_queue_family_index != info.present_queue_family_index) {
        // If the graphics and present queues are from different queue families,
        // we either have to explicitly transfer ownership of images between the
        // queues, or we have to create the swapchain with imageSharingMode
        // as VK_SHARING_MODE_CONCURRENT
        swapchain_ci.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
        swapchain_ci.queueFamilyIndexCount = 2;
        swapchain_ci.pQueueFamilyIndices = queueFamilyIndices;
    }
    

    上面的字段提供了创建交换链所需的更多基本信息。您可以在示例中检查其余的代码,以了解如何获得这些信息,以及如何填写create info结构的其余部分。

    创建交换链

    当交换链的 create info 结构填充完成,你现在就可以创建交换链了:

    res = vkCreateSwapchainKHR(info.device, &swapchain_ci, NULL, &info.swap_chain);
    

    这个调用创建了组成交换链的一组图像。在某种程度上,你需要对单个图像进行处理,这样你就可以告诉GPU哪些图像用于渲染。vkCreateSwapchainKHR()函数创建图像本身,因此保持了对句柄的跟踪。
    样例通过使用我们熟悉的查询模式来获得图像句柄的个数,通过调用

    vkGetSwapchainImagesKHR(info.device, info.swap_chain,
                            &info.swapchainImageCount, NULL);
    

    然后再次调用这个函数来获取一张图像句柄的列表,并将它们存储在info.buffer中。现在你有了一个目标图像句柄的列表。

    创建图像视图(Create Image Views)

    您需要告诉Vulkan,通过创建图像视图,您打算如何使用这些交换链图像。“视图”本质上是附加到一个资源的附加信息,该信息了如何使用该资源。

    属于图像的内存区域可以以多种方式排列,这取决于图像的预期用途。例如,图像可以是1D、2D或3D。或者可以有一系列的图像,等等。描述图像的格式(例如,VK_FORMAT_R8G8B8A8_UNORM)、组件的顺序和层信息也是很有用的。所有这些信息都是包含在VkImageView中的图像元数据。

    创建图像视图非常简单。在05-init_swapchain.cpp中找到VkImageViewCreateInfo 结构。并看到它被填充了你对2D framebuffer所期望的值。注意图像句柄本身存储在图像视图中。

    然后,您可以通过在info 数据结构中存储图像视图句柄来完成交换链的创建,以便以后使用。

    © Copyright 2016 LunarG, Inc

    更多相关内容
  • 压缩包中为 十字表法创建图的 C 文件源文件,及对应的PPT 博客《【经典算法实现 30】图的创建 --- 十字表法》 链接:https://blog.csdn.net/Ciellee/article/details/108199838
  • 文件转换三、创建一个泰安项目总结 前言 提示:这里可以添加本文要记录的大概内容: 最开始了解BSN是因为BSN的开发者大赛,如果你想尝试一下开发或学习区块链的相关知识,我认为是一个很好的入门平台。 来看一下...

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


    前言

    提示:这里可以添加本文要记录的大概内容:

    最开始了解BSN是因为BSN的开发者大赛,如果你想尝试一下开发或学习区块链的相关知识,我认为是一个很好的入门平台。
    来看一下它的简介:

    区块链服务网络BSN(“服务网络”或者“BSN”)是为开发者提供了一站式的区块链开发、部署和运行环境服务,整合了各大云服务商、框架商以及多个门户方的资源。因为涉及到编程开发、配置资源、部署应用、网关调用、以及密钥证书等多个方面,因此BSN官方门户(bsnbase.com)为开发者准备了帮助手册(http://kb.bsnbase.com/webdoc/view/Pub4028813e705bf9760170a92185bd1277.html),帮助开发者顺利掌握BSN的使用技巧,从而能够将BSN作为区块链开发和部署的首选工具。

    更多的内容你可以自己去他的网站上探索~,这里使用到的是BSN中提供的开放联盟链中的泰安链

    开放联盟链是用于部署和运行各类区块链应用的一站式区块链服务运行环境。与传统联盟链服务相比,开放联盟链的应用共享记账节点资源,不同应用的智能合约可以相互可见及调用,共享使用区块链数据账本;链外业务系统可以通过节点网关简单、快速接入区块链网络进行交易处理。
    目前BSN开放联盟链已推出文昌链(基于IRITA)、泰安链(基于FISCO BCOS)、武汉链(基于Ethereum)、唐山链(基于DBChain)、广元链(基于Everscale)和中移链(基于EOS),BSN后续将持续集成更多的底层框架,欢迎大家使用并提出宝贵的意见和建议。

    目前除了广元链支持密钥托管(这个模式适合不想写太多代码的开发者)之外,所有的其他开放联盟链都只能采用上传公外和上传账户地址的方式创建链账户。而广元链账户创建之前要注意提前创建好广元链的项目和部署智能合约


    一、创建一个泰安链账户

    选择链账户管理
    在这里插入图片描述
    点击图片右边的创建账户

    在这里插入图片描述
    取一个名字然后选择“上传公钥”模式,目前bsn已经取消了泰安链的密钥托管模式(没有密钥托管模式就不能线上部署智能合约)

    然后进入下一步,生成自己的公钥私钥。不用选择在线生成

    二、生成公钥私钥

    1.下载并安装openssl

    下载安装openssl并配置环境变量。https://www.openssl.org/source/
    找一个安装教程,到官网中下载最新版的openssl

    2.生成公钥

    打开命令行,终端输入 openssl 进入open ssl命令行(如果这一步都不行请检查有没有配置环境变量或环境变量配置是否正确)

    输入命令:

    官方文档中提供的命令是:ecparam -name prime256v1 -genkey -out key.pem。

    但是泰安链的框架是FISCO-secp256k1,其他的算法也要使用对应的加密算法,因此这里要改动一下语句,使用secp256k1 加密算法,注意算法不能错,错了就会导致测试失败无法成功创建。

    ecparam -name secp256k1 -genkey -out key.pem
    

    因为没有指定目录,所以我生成的文件保存在了C:\Users\Lenovo目录下。

    3.生成私钥

    输入命令 ec -in key.pem -pubout -out pub.pem 用key.pem文件中的私钥生成一个公钥文件pub.pem

    ec -in key.pem -pubout -out pub.pem
    

    执行结果:
    read EC key
    writing EC key

    4.生成签名文件

    先在已经生成的公钥私钥文件夹中新建一个文件data.txt,里面随便写上字符串(helloworld可在是程序员DNA里的)
    输入命令 dgst -sha256 -sign key.pem -out signature.bin data.txt 用key.pem文件中的私钥对data.txt文件进行签名生成签名文件signature.bin

     dgst -sha256 -sign key.pem -out signature.bin data.txt
    

    如果你报错了,那就赶紧检查一下的data.txt文件存不存在!

    5.签名验签

    输入命令 dgst -verify pub.pem -sha256 -signature signature.bin data.txt 用pub.pem文件中的公钥对data.txt和signature.bin文件进行签名验签

    dgst -verify pub.pem -sha256 -signature signature.bin data.txt
    

    执行结果:
    Verified OK

    6.文件转换

    如果显示Verified OK,输入命令 base64 -in signature.bin -out signature64.txt 将签名文件signature.bin转换成base64编码的 signature64.txt文件

    base64 -in signature.bin -out signature64.txt
    

    注意,这一步可能报错,我也不知道报错的原因是什么,尝试同样的语句再运行一遍就好了。。。很奇怪

    输入命令 pkcs8 -topk8 -inform PEM -in key.pem -outform PEM -nocrypt -out keypkcs8.pem 将key.pem文件中的私钥转为pkcs8格式

    pkcs8 -topk8 -inform PEM -in key.pem -outform PEM -nocrypt -out keypkcs8.pem
    

    本地自行保存好keypkcs8.pem文件,并将pub.pemdata.txtsignature64.txt中的全部内容对应复制到上传公钥模式页面的公钥、测试数据和签名数据文本框中进行验证并提交。
    在这里插入图片描述
    如果测试失败请检查使用的算法是否匹配,以及是否将文件中的全部内容复制到文本框中。


    三、创建一个泰安链项目

    在这里插入图片描述
    右侧开放联盟链中选择项目管理,点击右上角创建项目。
    输入项目名称和选择框架即可。框架选择后不可以更改。
    下载接入参数文件以便后续使用。

    总结

    到目前为止还不是很坑,下一个番外是关于建立你自己的FISCO-BCOS区块链的证书。

    展开全文
  • 一起来创建一个无向吧!

    千次阅读 2019-11-26 09:25:40
    创建图可是遍历的基础呢,虽然写了广度优先遍历()和深度优先遍历(DFS),但是自己对于创建图块还是想再来遍(once again?),基础也是很重要的。         我们都...

    前言:

            创建图可是遍历的基础呢,虽然写了广度优先遍历()和深度优先遍历(DFS),但是自己对于创建图这一块还是想再来一遍(once again?),基础也是很重要的。
            我们都知道图的储存结构表示有多种:邻接矩阵、邻接表十字链表、邻接多重表。这里重点交接邻接表(因为自己用的比较多),邻接矩阵也会涉及。其它的两种其实本质都是一样的,可以自己去深入。
    来!看一下邻接表相关概念:
             邻接表是图的一种链式存储结构。在邻接表中,对图中每个顶点vi建立一个单链表,把与vi相邻接的顶点放在这个链表中。邻接表中每个单链表的第一个节点存放有关顶点的信息,把这一结点看成链表的表头,其余结点存放有关边的信息,这样邻接表遍由两部分组成:表头结点表和边表。

    • (1)表头节点表:由所有表头结点以顺序结构的形式存储,以便可以随机访问任意顶点的边链表。扁头节点包括数据域链域两部分。其中数据域用于存储顶点vi的名称或其它有关信息;链域用于指向链表中第一个结点(即与顶点vi邻接的第一个邻接点)。
    • (2)边表:由表示图中顶点间关系的2n个边链表组成。边链表中边结点包括邻接点域数据域链域三部分。其中,邻接点域指示与顶点vi邻接的点在图中的位置;数据域存储边相关的信息,如权值等;链域指示与顶点vi邻接的下一条边的节点。

    一、邻接表创建无向图的代码:

    #include <iostream>
    using namespace std;
    
    #define MVNum 100                        	//最大顶点数
    #define OK 1
    
    typedef char VerTexType;					//顶点信息
    typedef int OtherInfo;						//和边相关的信息
    
    //- - - - -图的邻接表存储表示- - - - -
    typedef struct ArcNode{                		//边结点
        int adjvex;                          	//该边所指向的顶点的位置
        struct ArcNode *nextarc;          		//指向下一条边的指针
        OtherInfo info;                      	//和边相关的信息
    }ArcNode;
    
    typedef struct VNode{
        VerTexType data;                    	//顶点信息
        ArcNode *firstarc;                		//指向第一条依附该顶点的边的指针
    }VNode, AdjList[MVNum];               		//AdjList表示邻接表类型
    
    typedef struct{
        AdjList vertices;                 		//邻接表
        int vexnum, arcnum;              		//图的当前顶点数和边数
    }ALGraph;
    
    
    int LocateVex(ALGraph G , VerTexType v){
    	//确定点v在G中的位置
    	for(int i = 0; i < G.vexnum; ++i)
    		if(G.vertices[i].data == v)
    			return i;
       return -1;
    }//LocateVex
    
    int CreateUDG(ALGraph &G){
    	//采用邻接表表示法,创建无向图G
    	int i , k;
    
    	cout <<"请输入总顶点数,总边数中间以空格隔开:";
    	cin >> G.vexnum >> G.arcnum;				//输入总顶点数,总边数
        cout << endl;
    
    	cout << "输入点的名称,如 a " <<endl;
    	for(i = 0; i < G.vexnum; ++i){          	//输入各点,构造表头结点表
    		cout << "请输入第" << (i+1) << "个点的名称:";
    		cin >> G.vertices[i].data;           	//输入顶点值
    		G.vertices[i].firstarc=NULL;			//初始化表头结点的指针域为NULL
        }//for
    	cout << endl;
    
    	cout << "请输入一条边依附的顶点,如 a b" << endl;
    	for(k = 0; k < G.arcnum;++k){        		//输入各边,构造邻接表
    		VerTexType v1 , v2;
    		int i , j;
    		cout << "请输入第" << (k + 1) << "条边依附的顶点:";
    		cin >> v1 >> v2;                 		//输入一条边依附的两个顶点
    		i = LocateVex(G, v1);  j = LocateVex(G, v2);
    		//确定v1和v2在G中位置,即顶点在G.vertices中的序号
    
    		ArcNode *p1=new ArcNode;               	//生成一个新的边结点*p1
    		p1->adjvex=j;                   		//邻接点序号为j
    		p1->nextarc= G.vertices[i].firstarc;  G.vertices[i].firstarc=p1;
    		//将新结点*p1插入顶点vi的边表头部
    
    		ArcNode *p2=new ArcNode;                //生成另一个对称的新的边结点*p2
    		p2->adjvex=i;                   		//邻接点序号为i
    		p2->nextarc= G.vertices[j].firstarc;  G.vertices[j].firstarc=p2;
    		//将新结点*p2插入顶点vj的边表头部
        }//for
        return OK;
    }//CreateUDG
    
    int main(){
    	cout << "************采用邻接表表示法创建无向图**************" << endl << endl;
    	ALGraph G;
    	CreateUDG(G);
    	int i;
    
    	cout << endl;
    	cout << "*****邻接表表示法创建的无向图*****" << endl;
    
    	for(i = 0 ; i < G.vexnum ; ++i){
    		VNode temp = G.vertices[i];
    		ArcNode *p = temp.firstarc;
    		if(p == NULL){
    			cout << G.vertices[i].data;
    			cout << endl;
    		}
    		else{
    			cout << temp.data;
    			while(p){
    				cout << "->";
    				cout << p->adjvex;
    				p = p->nextarc;
    			}
    		}
    		cout << endl;
    	}
    	return 0;
    }//main
    
    

    给出一个列子:
    在这里插入图片描述
    在这里插入图片描述

    二、用邻接矩阵创建无向图

    
    #include <iostream>
    using namespace std;
    
    #define MaxInt 32767                    	//表示极大值,即∞
    #define MVNum 100                       	//最大顶点数
    #define OK 1	
     						
    typedef char VerTexType;              		//假设顶点的数据类型为字符型 
    typedef int ArcType;                  		//假设边的权值类型为整型 
    
    //- - - - -图的邻接矩阵存储表示- - - - -
    typedef struct{ 
    	VerTexType vexs[MVNum];            		//顶点表 
    	ArcType arcs[MVNum][MVNum];      		//邻接矩阵 
    	int vexnum,arcnum;                		//图的当前点数和边数 
    }AMGraph;
    
    int LocateVex(AMGraph G , VerTexType v){
    	//确定点v在G中的位置
    	for(int i = 0; i < G.vexnum; ++i)
    		if(G.vexs[i] == v)
    			return i;
       return -1;
    }//LocateVex
    
    int CreateUDN(AMGraph &G){ 
        //采用邻接矩阵表示法,创建无向网G 
    	int i , j , k;
    	cout <<"请输入总顶点数,总边数,以空格隔开:";
        cin >> G.vexnum >> G.arcnum;							//输入总顶点数,总边数
    	cout << endl;
    
    	cout << "输入点的名称,如a" << endl;
    
        for(i = 0; i < G.vexnum; ++i){   
    		cout << "请输入第" << (i+1) << "个点的名称:";
    		cin >> G.vexs[i];                        			//依次输入点的信息 
    	}
    	cout << endl;
        for(i = 0; i < G.vexnum; ++i)                			//初始化邻接矩阵,边的权值均置为极大值MaxInt 
    		for(j = 0; j < G.vexnum; ++j)   
    			G.arcs[i][j] = MaxInt;  
    	cout << "输入边依附的顶点及权值,如 a b 5" << endl;
    	for(k = 0; k < G.arcnum;++k){							//构造邻接矩阵 
    		VerTexType v1 , v2;
    		ArcType w;
    		cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
    		cin >> v1 >> v2 >> w;								//输入一条边依附的顶点及权值
    		i = LocateVex(G, v1);  j = LocateVex(G, v2);		//确定v1和v2在G中的位置,即顶点数组的下标 
    		G.arcs[i][j] = w;									//边<v1, v2>的权值置为w 
    		G.arcs[j][i] = G.arcs[i][j];						//置<v1, v2>的对称边<v2, v1>的权值为w 
    	}//for	
    	return OK; 
    }//CreateUDN 
    
    int main(){
    	cout << "采用邻接矩阵表示法创建无向网**************" << endl << endl;
    	AMGraph G;     int i , j;
    	CreateUDN(G);
    	
    	cout <<endl;
    	cout << "*****邻接矩阵表示法创建的无向网*****" << endl;
    	
    	for(i = 0 ; i < G.vexnum ; ++i){
    		for(j = 0; j < G.vexnum; ++j){
    			if(j != G.vexnum - 1){
    				if(G.arcs[i][j] != MaxInt)
    					cout << G.arcs[i][j] << "\t";
    				else
    					cout << "∞" << "\t";
    			}
    			else{
    				if(G.arcs[i][j] != MaxInt)
    					cout << G.arcs[i][j] <<endl;
    				else
    					cout << "∞" <<endl;
    			}
    		}
    	}//for
    	cout <<endl;
    	return 0;
    }//main
    

    后记:

            只有掌握基础的存储结构,才可以更好的往下走。冲鸭!如有更好的结构,评论哦!

    展开全文
  • 图片生成链接最简单的方法

    万次阅读 2020-12-14 10:29:42
    有时候我们需要将几张图片生成链接或者二维码,...我们的目的非常简单,就是希望别人扫一扫或者直接点击就能看到一连串的图片,而不是像某些图床工具把图片生成一个一个的链接。 首先我们打个腹稿,在心中想一想如何

    有时候我们需要将几张图片生成链接或者二维码,方便进行各种场景的展示和分享。因为链接是可以在各种设备和系统打开的。比如微信好友或朋友圈发一些类似H5页面的链接,类似于公众号一样自带缩略图和简介的小方格.如果自己去申请公众号来设置,会异常复杂.我们知道公众号虽然门槛低,但是从来没有接触过的人会在使用上有困难。但是有一些简单好用的方法也一样可以达到这个效果。在这里插入图片描述

    我们的目的非常简单,就是希望别人扫一扫或者直接点击就能看到一连串的图片,而不是像某些图床工具把图片生成一个又一个的链接。

    首先我们打个腹稿,在心中想一想如何设置自己的微信分享小方块。比如:显示什么图片,什么标题,什么简介这三点。因为您上传的第一张图片将作为微信缩略图展示的小方格。 我们进入图床制作器进行图片的上传和阅读次数的设置比如麦瓜图床。如果对展示顺序有要求的,可以将图片按字母或者数字的排列顺序进行图片的命名。然后我们就可以将图片进行上传了。 (上传的方式非常简单易用,直接把图片拖拽,或者选择图片进行上传,手机上操作也是一样的简便,可以一次性选择多张图片进行上传) 上传之后,会提示是否上传成功。待上传成功之后,我们再进行下一步的设置,图片链接打开的次数和每次的阅读时间。如果想设置阅后即焚的效果,可以设置打开次数1,阅读时间60秒,这样别人在打开一次之后就无法打开第二次了。在这里插入图片描述
    在这里插入图片描述
    在生成链接之后就可以分享出去了!有两种方式可以展示图片,一种是滑动的轮播图片,还有一种是非常适合长图的自适应轮播图。 而且我们还可以根据追踪链接来进行阅读记录的查看! 链接可以很快的生成为二维码,在该工具的同一页面下,输入生成的图片链接,会自动转成一个二维码,我们既可以用链接去直接分享,又可以把二维码贴在某个地方,供大家扫一扫进行查阅在这里插入图片描述
    在图片分享出去之后,我们依然可以对该链接和二维码进行追踪,比如该链接打开了几次?在哪个城市打开的?打开的设备都是什么?是不是用微信打开还是用电脑打开的等待。
    能追踪就意味着能控制:我们可以在将图片分享出去之后,对图片进行不换链接换图片的方式进行更改。在这里插入图片描述

    展开全文
  • 联盟是一个虚拟组织,由多个机构组成。联盟机构可以: 共享联盟区块链 创建区块链应用,并共享给联盟内的其他机构 创建联盟 登录控制台,点击 产品与服务 > 区块链 >...
  • 在github中快速创建文件夹以及生成文件链接,简单明了,一步到位,傻瓜式的创建
  • 创建一个简单的单链表

    万次阅读 多人点赞 2020-05-15 23:33:04
    数据结构创建单链表的基本操作 一、构造单链表的结构体 typedef struct LNode { ElemType data;//结点的数据域 struct LNode*next;//结点的指针域 }LNode,*LinkList;... L)//创建一个空的单链表 { L = new LNode
  • 如何创建一个完整的SpringBoot项目 Spring Boot项目可以直接创建然后配置,也可以通过创建Maven项目的方法创建SpringBoot项目 本文主要讲述的是创建一个Maven项目,并将其转为一个SpringBoot项目 1、新建一个...
  • 使用Numpy创建纯色图片

    千次阅读 2019-06-03 00:20:40
    那就意味着可以通过numpy来创建一个图片 如果电脑上没有numpy的话需要先装一下 pip install numpy 可以通过numpy的zeros来创建一个空数组 import cv2 as cv import numpy as np def create_image(): ...
  • Spring是怎么创建一个Bean的?

    千次阅读 2020-02-12 13:31:38
    需要看源码直接看AbstractAutowireCapableBeanFactory#doCreateBean 直接看下流程: 流程: 创建实例:createBeanInstance(beanName, mbd, args)创建一个带有bean实例的BeanWrapper 收集注解:通过...
  • 创建一个成功的NFT,总共分几步?

    千次阅读 2022-04-11 11:35:17
    看到消息说某某人通过 NFT 赚得盆满钵满的时候,你的脑海会不会闪过一个念头——“不如我也来创个项目吧,或许下一个通过区块链致富的就是我呢?” 创建 NFT 的第一步,就是...那么创建一个成功的NFT,总共分几步?.
  • 一:创建一个SpringBoot项目

    万次阅读 2019-01-07 17:04:14
    spring boot 它的设计目的就是为例简化开发,开启了各种自动装配,你不想写各种配置文件,引入相关的依赖就能迅速搭建起一个web工程。它采用的是建立生产就绪的应用程序观点,优先于配置的惯例,慢慢的,你会爱上它...
  • 1.创建一个目录/dzqc 提示: windows下的路径样式为c: \dzqc\ test,而linux下的路径样式为 /dzqc/test 因此/dzqc就可以看做是c:\dzqc,不同的是 windows系统下还有D,E等盘, linux下就只有/为所有目录的顶点。 英文 ...
  • 安装anaconda并创建一个tensorflow环境的详细教程

    千次阅读 多人点赞 2020-11-27 20:45:56
    安装Anaconda并创建tensorflow环境超级详细教程 二话不说先上资源链接: 百度云盘链接地址: https://pan.baidu.com/s/1Me9cLJ5LRhxuDmXoLkOIjA 提取码:yq23 (此版本为本人将要演示的安装版本) 如果感觉此版本不太...
  • 一个js对象,除了自己设置的属性外,还会自动生成proto、class、extensible属性,其中,proto属性指向对象的原型。 对象的属性也有writable、enumerable、configurable、value和get/set的配置方法。 对象的创建方式...
  • 在这种结构中,稀疏矩阵中的每一个非零元素对应一个结点,每个结点有5个域组成,其中3个数据域分别存放结点的行、列及元素值,2个指针域存放向下的指针(down)与向右的指针(right)如2.20所示。由于这种结点链接成...
  • 如下所示,它是一个基于AUTOSAR的虚拟集群,可以在Windows和Linux上进行模拟。 关键点 1. BSW 1.1集成ArcCore AUTOSAR 3.1 BSW 通讯:Can(CanFD)CanIf PduR Com SoAd J1939Tp 诊断:CanTp Dcm DoIP Dem 系统...
  • 看到一个图片,不要将其当作图片,在你眼里,其实就是一个一个小格子,每个格子都有一个数值,也就是一个矩阵,格子里的数值其实就是灰度值,对于多通道的彩色图片来说,其实就相当于多个灰度的叠加,只是说叠加的...
  • ln(即link) 的功能是为某一个文件在另外一个位置建立一个同步的链接。有两种链接方式,一种是硬链接(hard link),另一种是符号链接(symbolic link),又称软链接。硬链接和原有文件是存储在同一物理地址的两个...
  • 有人说 Crypto 领域的投资发展史,就是部 ETH 扩容史。 一直以来,不管是在比特币网络或以太坊网络上,与传统网络相比,「速度」一直以来都是待解决的问题,Gas fee昂贵,用户为了扩大收益率,让资产在不同...
  • 创建一个最简单的链表,插入和删除

    万次阅读 多人点赞 2018-09-04 21:38:43
    创建一个链表 一、头插法创建链表:   #include &lt;stdio.h&gt; struct list { int num; struct list *next; }; typedef struct list list_single; list_single *creat_list_tail(int n)//尾插法...
  • 定义一个抽象类,具体的过滤需要实现这个抽象类中的doFilter抽象方法 public abstract class TitleFilterChain { protected static Logger logger = LoggerFactory.getLogger...
  • RobotStudio仿真—Smart组件创建动态输送

    万次阅读 多人点赞 2017-06-20 19:42:12
    、Smart组件 创建受信号与属性控制的动作组件。 不同于事件管理器的是,它适用于中大型工作站应用中,显示动态工作流程,更直观。 二、码垛工作站 产品从输送一端产生,然后沿着输送运动...
  • dubbo调用/过滤器创建分析

    千次阅读 2017-02-01 12:15:48
    功能的实现是通过Dubbo内置的Filter或用户自定义的Filter来创建调用完成。当发起方法调用时,会执行调用各个结点的方法,以完成一些处理工作。 调用/过滤器创建分析 调用的构
  • windows 系统创建文件链接 mklink

    万次阅读 2018-06-16 13:39:09
    mklink [选项] 链接文件 目标文件链接文件:即我们要创建的链接到某个目录或文件的“类似快捷方式”的文件目标文件:要链接到的目录或文件常用选项: /D:创建目录链接(若无则是创建文件链接) 其他两选项用得不...
  • sqlserver中创建链接服务器图解教程

    万次阅读 2017-12-01 14:54:45
    1.展开服务器对象-->链接服务器-->右击"新建链接服务器"   注意:必须以数据库管理员身份登录(通常也就是sa帐号)后,才...现在测试一下,用帐号user本地登录SqlServer,新建一个查询,输入Select * From [链接服
  • 、编写示例智能合约 智能合约: 它是段代码和数据的集合,可以部署以太坊网络上运行。类似于Java程序,Java程序通过Java虚拟机(JVM)将代码解释字节进行执行,以太坊的智能合约通过以太坊虚拟机(EVM)解释成...
  • 一个js对象,除了自己设置的属性外,还会自动生成proto、class、extensible属性,其中,proto属性指向对象的原型。 对象的属性也有writable、enumerable、configurable、value和get/set的配置方法。 对象的创建方式...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,132,429
精华内容 452,971
关键字:

如何创建一个图链