精华内容
下载资源
问答
  • NULL 博文链接:https://dreamzhong.iteye.com/blog/1201459
  • 组合双向拍卖分析为基础,建立了相关的数学模型,分别对单一回合和多个回合的组合双向拍卖交易机制进行了研究,证明多回合组合双向拍卖能更大地提高社会福利,也为进一步...
  • 基于组合双向拍卖的网格定价算法,丁鹏,马晓雷,针对网格环境中资源分配的特点,以网格经济中的组合双向拍卖模型为基础,分析传统组合双向拍卖模型中的优缺点,提出了一种新的组
  • 基于组合双向拍卖理论的云计算资源定价研究,薛辉,吴俊,随着云计算的不断发展,各大企业都开始提供云计算服务,云计算的市场规模在不断地扩大,云计算资源定价相关研究也越来越多,本文
  • 基于多归属组合双向拍卖的SDN资源价格协商算法研究
  • 针对物联网中数据实效性强的特点,结合物联网搜索中用户的高异构性和动态性,提出一种基于组合双向拍卖的搜索任务分配模型,从市场供求关系的角度描述了搜索发起者、搜索参与者和搜索引擎之间的关系。首先引入了竞价...
  • JB/T 6644-2007 滚动轴承 滚针和双向推力圆柱滚子组合轴承pdf
  • 哈希表+双向链表的组合使用

    千次阅读 2016-03-24 13:47:38
    首先看一下常用的hash表与双向链表结组合使用,这样的组合一般使用在网络通讯中,接收端收到大量的新数据消息, 将消息先存储到hash中,查询快捷,方便。 哈希表是由一个表头加上若干个节点组成,每个...

    在一个老牌通信公司工作几年,做的核心网项目开发,整天关注的是call flow,所参与的项目基本和MM和Call Control相关,

    大多重点在项目开发逻辑,以及信令的解析和分析上。

    公司内部代码有很多优秀的设计细节,和架构方式,只不过平时在此宏观的架构的基础上添加新代码,使用优秀简洁的接口,很少

    仔细分析这些代码的优势所在。其中包括网络通信,进程间通信,以及多线程,共享内存,进程管理,状态机,以及定时器,

    各种log机制。

    最近有了一些闲暇时间,准备细细阅读基础代码,将一些优秀的设计理念和方法,加以整理总结。


    首先看一下常用的hash表与双向链表结组合使用,这样的组合一般使用在网络通讯中,接收端收到大量的新数据消息,

    将消息先存储到hash中,查询快捷,方便。


    哈希表是由一个表头加上若干个节点组成,每个节点都是一个双向链表,数据对象实际是存储在哈希表节点的双向链表节点中。

    由于每个节点都是一个双向链表,链表的每个节点中存储数据。

    这样的好处是,如果随机产生的hash值如果相同,也可以使用,也不用重新产生命中的相同的hash值,可以直接存入对应的双向链表中。

    这需要一个很好的散列化的hash函数,将数据对象均匀分布到节点的链表中。


    哈希表的表头中定义了:

    1. 哈希表的节点的最大个数变量

    2. 产生哈希值的哈希函数指针变量的定义

    3. 用于查找的对比函数指针变量的定义

    4. 定义存储节点的数组

    5. 存储数据对象的个数

    双向链表定义:

    1. 带有双向指针的表头

    2. 带有双向指针的表尾

    3. 带有双向链表中存储数据的个数


    哈希表的表头定义如下:

    /**
     * data structure of hash table
     */
    typedef struct _HASHTABLE
    {
            /// static configurable data of hash table
            int             numBuckets;     /// number of bucket in this hash table
            HASHFUNCPTR     hashFunc;       /// hash function from key to bucket
            COMPFUNCPTR     cmpFunc;        /// comparison function to the key of the object
            DLIST_P         bucketArray;    /// array of buckets in this hash table
    
            /// dynamic data of hash table
            int             numObjects;     /// number of objects in this hash table
    } HASHTABLE_T, *HASHTABLE_P;


    双向链表的定义如下:

    /**
     *
     * The double linked list is used to manage the list of objects for specific purpose.
     * It allows the user to insert the object into or remove it from the list dynamically.
     *
     * To link them together, the object MUST contain GEN_NODE_T as the first element in its
     * structure, so that we can cast the pointer to the object to the GEN_NODE_P. 
     *
     * The structure of double linked list looks like the following.
     *
     *		+----------+         +----------+                         +----------+
     *     NULL <---+-- prev   |<--------+-- prev   |<--------       <--------+-- prev   |
     *		+----------+         +----------+           ...           +----------+
     *		|   next --+-------->|   next --+-------->       -------->|   next --+--->NULL
     *		+----------+         +----------+                         +----------+
     *		|   data   |         |   data   |                         |   data   |
     *		+----------+         +----------+                         +----------+
     *		     ^                                                         ^
     *        	     |                                                         |
     *   		     |                                                         |       
     *  		 head(list)                                                tail(list)    
     *
     */
    
    /**
     * data structure of double linked list
     */
    typedef struct _DLIST
    {
    	/// dynamic data of this list
    	GEN_NODE_P	head;		/// pointer to the head node of this list
    	GEN_NODE_P	tail;		/// pointer to the tail node of this list
    	int		numObjects;	/// current number of nodes in this list
    } DLIST_T, *DLIST_P;

    /**
     * data structure of general purpose node used in double linked list
     *
     */
    typedef struct _GEN_NODE {
            struct _GEN_NODE        *prev;          /// pointer to the previous node in the list
            struct _GEN_NODE        *next;          /// pointer to the next node in the list
    } GEN_NODE_T, *GEN_NODE_P;
    



    哈希表的创建:创建函数中有带入两个函数指针类型的函数,一个是hash函数,一个是对比函数,在头文件中事先定义好对应的函数指针。

    哈希函数指针的定义

    typedef unsigned int    (* HASHFUNCPTR)(const void *key);
    对比函数指针的定义
    typedef int     (* COMPFUNCPTR)(const void * obj, const void *key);
    

    HASHTABLE_P HashTable_create(int numBuckets, HASHFUNCPTR hashFunc, COMPFUNCPTR cmpFunc)
    {
            HASHTABLE_P ht = NULL;
    
            assert((hashFunc != NULL) && (cmpFunc != NULL) && (numBuckets > 0));
    
            ht = (HASHTABLE_P)calloc(1, sizeof(HASHTABLE_T) + sizeof(DLIST_T) * numBuckets);
    
            if (ht != NULL) {
                    ht->numBuckets = numBuckets;
                    ht->hashFunc = hashFunc;
                    ht->cmpFunc = cmpFunc;
                    ht->bucketArray = (DLIST_P)(ht + 1);
            }
    
            return ht;
    }

    这个函数是创建整个哈希表,为哈希表申请内存空间,包括哈希表的表头,还同时创建了numBuckets个双向链表。

    在此用的申请空间的函数是calloc,在申请完空间后,会自动将空间清空。这是一个好的使用方法。

    将哈希函数和对比函数的函数指针,赋入函数。

    具体使用方法如下:

    /* Max Number of Active CSFB CALL in Queue */
    #define MAX_CSFB_CALL           4096

            g_pPgrHash  = HashTable_create(MAX_CSFB_CALL, s102PgrHash, s102PgrCmp);</span>
            if (g_pPgrHash  == NULL)
            {
                    UX_ID_ELOG(ES1020623, "Unable to HashTable_create g_pPgrHash \n");
                    UXTPCU(A21_KILL_SIG);
            }
    



    销毁整个哈希表:销毁整个hash表,可以先调用清空此哈希表中所有数据的值,然后将申请的hash表的内存空间free掉。

    void HashTable_destroy(HASHTABLE_P ht, FREEFUNCPTR freeFunc)
    {
            assert(ht != NULL);
    
            // delete all the object from each bucket
            HashTable_delAllObjs(ht, freeFunc);
    
            // release the memory for hashtable
            free(ht);
    
            return;
    }
    



    哈希表插入数据:

    可以根据查找函数HashTable_getBucket(),此函数的功能是根据key值,调用hash函数,产生hash值,返回对应数组中双向链表的地址。

    然后调用双向链表的插入函数,将数据加入到双向链表的表尾处。

    int HashTable_addObj(HASHTABLE_P ht, void *key, void *obj)
    {
            DLIST_P bucket = NULL;
    
            assert((ht != NULL) && (key != NULL) && (obj != NULL));
    
            bucket = HashTable_getBucket(ht, key);
            if (bucket == NULL) return HASHTABLE_ERROR_HASHFAIL;
    
            if (DList_addObjTail(bucket, obj) != DLIST_NO_ERROR) {
                    return HASHTABLE_ERROR_INSERTFAIL;
            }
    
            ht->numObjects++;
            return HASHTABLE_NO_ERROR;
    }
    


    双向链表添加数据的函数如下:

    int DList_addObjTail(DLIST_P list, void *obj)
    {
            assert((list != NULL) && (obj != NULL));
    
            GEN_NODE_P node = (GEN_NODE_P)obj;
            node->prev = list->tail;
            node->next = NULL;
    
            if (list->tail == NULL) {
                    if ((list->head != NULL) || (list->numObjects != 0)) {
                            return DLIST_ERROR_INCONSISTENT;
                    }
    
                    list->head = node;
            } else {
                    node->prev->next = node;
            }
    
            list->tail = node;
            list->numObjects++;
    
            return DLIST_NO_ERROR;
    }

    OBJ即为插入的数据对象,此数据对象有个要求,此数据结构的第一个变量必须是GEN_NODE_T      link;   

    双向链表可以从head往里插入数据,也可从tail处插入数据。

    此次是从tail处插入数据。

    1. 首先将数据对象的首地址强制转换成节点类型,这就是为什么数据对象的结构体的第一个变量为什么必须是GEN_NODE_T 类型的缘故,将数据前后链接。

    2. 从结尾处插入数据,将此节点的前驱指向双向链表的tail,将此节点的后继设为空。

    3. 由于是双向链表,前一个数据,需要将后继改为新加入的节点,如果此链表为空,可直接将链表的头指向此数据对象节点。

    4.从结尾出插入数据,新加入的数据即为tail,将链表的tail指向新加入的数据节点

    5. 将链表中数据对象的个数加1


    使用方法如下:

                           // add this csr into hash table with given key
                            retVal = HashTable_addObj(g_pCsrHash, (void *)mnidPtr, (void *)&g_s102csr[objId]);
    
                            if (retVal != HASHTABLE_NO_ERROR) {
                                    UX_ID_ELOG( ES1020576, "Failed to call HashTable_addObj to add the csr index %d : retval: %d", objI\
    d, retVal);
                                    /// free the Correlation Id for other request message
                                    Allocator_freeObject(g_pCsrIdleList, objId);
                                    index = -1;
                            }


    哈希表查找数据:

    void *HashTable_findObj(HASHTABLE_P ht, void *key, DLIST_P *bucket)
    {
            DLIST_P bkt = NULL;
            void    *obj = NULL;
    
            assert((ht != NULL) && (key != NULL));
    
            bkt = HashTable_getBucket(ht, key);
            if (bkt != NULL) {
                    obj = DList_findObj(bkt, ht->cmpFunc, key);
            }
    
            if (bucket != NULL) *bucket = bkt;
    
            return obj;
    }
    

    根据查找函数HashTable_getBucket 获取key值应该放得节点位置

    根据key值,调用hash函数,产生hash值,返回对应数组中双向链表的地址。

    根据对比key,在此双向链表中查询此对象key值,如果找到,返回对应节点的地址。

    根据节点地址,可获取此节点中对象的数据。

    从双向链表中查找数据的函数如下:

    void* DList_findObj(DLIST_P list, COMPFUNCPTR cmpFunc, void *key)
    {
            assert((list != NULL) && (cmpFunc != NULL) && (key != NULL));
    
            GEN_NODE_P      node = list->head;
            int             count = 0;
    
            while ((node != NULL) && (count < list->numObjects)) {
                    if ((* cmpFunc)((void *)node, key) == 0) return (void *)node;
                    count++;
                    node = node->next;
            }
    
            return NULL;
    }
    通过对比函数将key值和链表中的数据key值进行对比,返回节点地址。


    哈希表删除一条数据:

    void *HashTable_removeObj(HASHTABLE_P ht, void *key)
    {
            DLIST_P bucket = NULL;
            void    *obj = NULL;
    
            assert((ht != NULL) && (key != NULL));
    
            obj = HashTable_findObj(ht, key, &bucket);
    
            if (obj != NULL) {
                    if (bucket != NULL) {
                            DList_removeObj(bucket, obj);
                            ht->numObjects--;
                    } else {
                            return NULL;
                    }
            }
    
            return obj;
    }
    

    在此哈希表中删除一条数据包含了哈希表查找数据,然后再双向链表中将此数据删除,hash表中数据总个数减1。


    双向链表删除一个对象的函数如下:

    void DList_removeObj(DLIST_P list, void *obj)
    {
            assert(list != NULL);
    
            GEN_NODE_P node = (GEN_NODE_P)obj;
    
            if (node == NULL) return;
    
            if (node->prev == NULL) {
                    // if the object is the head of list, set the head to the next object
                    list->head = node->next;
            } else {
                    // otherwise, let the previous one links to the next object
                    node->prev->next = node->next;
            }
    
            if (node->next == NULL) {
                    // if the object is the tail of list, set the tail to the previous object
                    list->tail = node->prev;
            } else {
                    // otherwise, let the next one links to the previous object
                    node->next->prev = node->prev;
            }
    
            // clear the linkage of this object
            node->prev = NULL;
            node->next = NULL;
    
            list->numObjects--;
            return;
    }
    

    删除一个对象的流程如下:

    1. 首先将数据对象的首地址强制转换成节点类型,这就是为什么数据对象的结构体的第一个变量为什么必须是GEN_NODE_T 类型的缘故,将数据前后链接,便于操作。

    2. 如果要删除的节点的前驱是空,表明此节点为head,将此节点的后继设为head即可

    3. 如果要删除的节点的前驱不是空,将此节点前驱的后继指向此节点的后继。

    4. 如果要删除的节点的后继是空,表明此节点为tail,将此节点的前驱设为tail即可

    5.  如果要删除的节点的后继不是空,将此节点后继的前驱设为此节点的前驱

    6. 将此节点前驱后继,设为null

    7.链表中的数据总个数减1


    清空整个哈希表:

    void HashTable_delAllObjs(HASHTABLE_P ht, FREEFUNCPTR freeFunc)
    {
            int i;
    
            assert(ht != NULL);
    
            for (i=0; i<ht->numBuckets; i++) {
                    DList_delAllObjs(&ht->bucketArray[i], freeFunc);
            }
    
            ht->numObjects = 0;
    
            return;
    }
    

    获取哈希表中存储数据对象的个数:

    int HashTable_getSize(HASHTABLE_P ht)
    {
            assert(ht);
    
            if (ht->numObjects < 0) return HASHTABLE_ERROR_INCONSISTENT;
            return ht->numObjects;
    }
    

    根据key值获取哈希表数据节点的位置:

    DLIST_P HashTable_getBucket(HASHTABLE_P ht, void *key)
    {
            int slot = 0;
    
            assert((ht != NULL) && (key != NULL));
    
            slot = (* ht->hashFunc)(key);
            if ((slot < 0) || (slot >= ht->numBuckets)) return NULL;
    
            return &ht->bucketArray[slot];
    }
    

    根据key值,调用hash函数,产生hash值,返回对应数组中双向链表的地址。


    以上为hash表的操作中套用双向链表的操作方法。

    展开全文
  • vlookup函数是工作中excel中最常用的查找函数。...本文分别图文详解使用index+Match函数组合实现反向、双向等复杂的表格查找的方法。 1、反向查找 【例1】如下图所示,要求根据产品名称,查找编号。分析...

    http://www.officezhushou.com/excelhansu/4825.html

    vlookup函数是工作中excel中最常用的查找函数。但遇到反向、双向等复杂的表格查找,还是要请出今天的主角:index+Match函数组合。本文分别图文详解使用index+Match函数组合实现反向、双向等复杂的表格查找的方法。

    1、反向查找

    【例1】如下图所示,要求根据产品名称,查找编号。
    使用index+Match函数组合实现反向、双向等复杂的表格查找
    分析:

    先利用Match函数根据产品名称在C列查找位置

    =MATCH(B13,C5:C10,0)

    再用Index函数根据查找到的位置从B列取值。完整的公式即为:

    =INDEX(B5:B10,MATCH(B13,C5:C10,0))

    2、双向查找

    【例2】如下图所示,要求根据月份和费用项目,查找金额
    使用index+Match函数组合实现反向、双向等复杂的表格查找
    分析:

    先用MATCH函数查找3月在第一行中的位置

    =MATCH(B10,$A$2:$A$6,0)

    再用MATCH函数查找费用项目在A列的位置

    = MATCH(A10,$B$1:$G$1,0)

    最后用INDEX根据行数和列数提取数值

    INDEX(区域,行数,列数)

    =INDEX(B2:G6,MATCH(B10,$A$2:$A$6,0),MATCH(A10,$B$1:$G$1,0))

    3、多条件查找

    【例3】如下图所示,要求根据入库时间和产品名称,查找入库单价。
    使用index+Match函数组合实现反向、双向等复杂的表格查找
    分析:

    由于match的第二个参数可以支持合并后的数组所以可以直接进行合并查找:

    =MATCH(C32&C33,B25:B30&C25:C30,0)

    查找到后再用INDEX取值

    =INDEX(D25:D30,MATCH(C32&C33,B25:B30&C25:C30,0))

    由于公式中含有数组运算(一组数同另一组数同时运算),所以公式需要按ctrl+shift+enter三键完成输入

    转载于:https://blog.51cto.com/1971372/2143434

    展开全文
  • 电路配置,电路拓扑系列,降压模式有源钳位电路以及具有高频(HF)链接的双向双向降压-升压dc-dc斩波模式逆变器的瞬时输出电压反馈控制策略分别为提出并在本文中进行了充分研究。 给出了关键电路参数的稳态原理特性...
  • UWB模块SKU609 是一款蓝牙UWB组合模块,蓝牙方案采用NRF52832、UWB方案采用DW1000。可以广泛应用于UWB(TDOA、TWR)高精度定位系统,也可以应用于基于UWB的精准双向测距。内嵌加速传感器,可以实现静止和运动条件下...
  • 双向队列deque:第一次用,队列、栈肯定不能用,因为既有先进先出要求,又有先进后出要求(removeLast & 用于构造ArrayList);数组可以,但是要多传一个下标值,比较麻烦。 用nowIndex来保证不会重复,相当于从...

    题目描述

    • 讲道理,像这种找可行集合解的问题,基本上都可以通过回溯 + 剪枝来做
      在这里插入图片描述

    思路 & 代码

    • sort()用于优化,多一个剪枝判断,其实也可以不写
    • 双向队列deque:第一次用,队列、栈肯定不能用,因为既有先进先出要求,又有先进后出要求(removeLast & 用于构造ArrayList);数组可以,但是要多传一个下标值,比较麻烦。
    • 用nowIndex来保证不会重复,相当于从左到右遍历所有结果,而不重复遍历
    • deque只用一条就够了,在回溯过程中不断调整内容
    • nowNum > target的情况直接剪枝即可,已经没有继续走的必要了
    class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            // 基于排序后的优化剪枝做法
            List<List<Integer>> ans = new ArrayList<>();
            // 使用一个双向队列
            Deque<Integer> path = new ArrayDeque<>();
            // 回溯 + 双向队列
            Arrays.sort(candidates);
            back(candidates,0,target,0,path,ans);
            return ans;
        }
        // 找到正确结果后,一个个回去
        // 不重复:用nowIndex保证
        void back(int[] candidates, int nowNum, int target, int nowIndex, 
        Deque<Integer> path,List<List<Integer>> ans){
            // 剪枝
            if(nowNum > target){
                return;
            }
            // 找到了
            else if(nowNum == target){
                ans.add(new ArrayList<>(path));
                return;
            }
            // 小于
            else{
                for(int i=nowIndex;i<candidates.length;i++){
                	// 因为排序过了,所以此处可以剪枝
                    if(nowNum + candidates[i] > target){
                        return;
                    }
                    path.addLast(candidates[i]);
                    back(candidates,nowNum+candidates[i],target,i,path,ans);
                    path.removeLast();
                }
            }
        }
    }
    
    展开全文
  • 开始学习UML类图中的类与类之间的关系中的时候,其中依赖,组合和聚合关系比较容易混淆,下面我以代码和类图的形式将这些关系呈现出来。希望能够对困惑者有所帮助。 我使用的建模工具为powerdesigner。关联是一种...

         开始学习UML类图中的类与类之间的关系中的时候,其中依赖,组合和聚合关系比较容易混淆,下面我以代码和类图的形式将这些关系呈现出来。希望能够对困惑者有所帮助。

     我使用的建模工具为powerdesigner。

     

    关联是一种结构化的关系,指一种对象和另一种对象有联系。给定有关联的两个类,其中一个类的对象包含另一个类的对象,关联有单向关联和双向关联。

     

    多重性关联关系

             多重性关联关系又称为重数性关联关系,表示一个类的对象与另一个类的对象连接的个数。在UML中多重关系可以直接在关联直线上增加一个数字表示与之对应的另一个类的对象的个数

    聚合关系指的是整体与部分的关系。通常在定义一个整体类后,再去分析这个整体类的组成结构,从而找出一些成员类,该整体类(容器类)和成员类之间就形成了聚合关系。在聚合关系中,类A是类B的一部分,但是类A可以独立存在,在UML中,聚合关系用带空心菱形的直线表示。

     

    组合关系也表示类之间整体和部分的关系,但是组合关系中部分和整体具有相同的生存期。一旦整体对象不存在,部分对象也将不存在,部分对象与整体对象之间具有共生死的关系。在组合关系中,类A包含类B,而且可以控制类B的生命周期。类A控制类B的生命周期意味着类B的存在依赖于类A。在UML中,组合关系用带实心菱形的直线表示。

     

    依赖关系是一种使用关系,特定事物的改变有可能会影响到使用该事物的其他事物,反之不成立,在需要表示一个事物使用另一个事物时使用依赖关系。通常情况下,依赖关系体现在某个类的方法使用另一个类作为参数。在UML中也可以在其他的事物之间使用依赖关系,如节点之间的关系。依赖关系用带箭头的虚线表示,由依赖的一方指向被依赖的一方。

     

     

     

    (1)

    public class A {

       /** @pdRoleInfo migr=no name=B assc=association1 mult=1..1 type=Aggregation */

       public B b;

     

    }

    /** @pdOid 8f2cf0c8-d0d0-4b51-86f6-e2f63840b77f */

    public class B {

    }

     

     

    (2)

    /** @pdOid fe9426ca-b27b-4398-855c-e925f7d97e4a */

    public class C {

       /** @pdRoleInfo migr=no name=D assc=association2 coll=java.util.Collection impl=java.util.HashSet mult=0..* type=Aggregation */

       public java.util.Collection<D> d;

      

      

       /** @pdGenerated default getter */

       public java.util.Collection<D> getD() {

          if (d == null)

             d = new java.util.HashSet<D>();

          return d;

       }

      

       /** @pdGenerated default iterator getter */

       public java.util.Iterator getIteratorD() {

          if (d == null)

             d = new java.util.HashSet<D>();

          return d.iterator();

       }

      

       /** @pdGenerated default setter

         * @param newD */

       public void setD(java.util.Collection<D> newD) {

          removeAllD();

          for (java.util.Iterator iter = newD.iterator(); iter.hasNext();)

             addD((D)iter.next());

       }

      

       /** @pdGenerated default add

         * @param newD */

       public void addD(D newD) {

          if (newD == null)

             return;

          if (this.d == null)

             this.d = new java.util.HashSet<D>();

          if (!this.d.contains(newD))

             this.d.add(newD);

       }

      

       /** @pdGenerated default remove

         * @param oldD */

       public void removeD(D oldD) {

          if (oldD == null)

             return;

          if (this.d != null)

             if (this.d.contains(oldD))

                this.d.remove(oldD);

       }

      

       /** @pdGenerated default removeAll */

       public void removeAllD() {

          if (d != null)

             d.clear();

       }

     

    }

     

    public class D {

    }

     

     

     

    (3)EF的代码与CD的代码一样的

     

    4GH的代码与AB的代码一样的

     

     

    /** @pdOid fed71090-8e24-4c11-8e21-6d81f0accf97 */

    public class H {

    }

    public class G {

       /** @pdRoleInfo migr=no name=H assc=association4 mult=1..1 type=Aggregation */

       public H h;

     

    }

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    1

    public class A {

       /** @pdRoleInfo migr=no name=B assc=association1 mult=1..1 */

       public B b;

     

    }

    public class B {

    }

     

    2)与上面CD的代码类似

    3

    public class E {

       /** @pdRoleInfo migr=no name=F assc=association3 mult=0..1 */

       public F f;

     

    }

    /** @pdOid 2981ae48-b4c0-4a54-918d-1886312657be */

    public class F {

    }

     

    4)依赖关系:

     

    /** @pdOid 23a21238-0ca0-458a-866f-14032ebfc752 */

    public class G {

    }

     

    /** @pdOid 48fdcbf8-5523-4eed-9ee9-ea8ca7b23a38 */

    public class H {

    }

     

     

     

     

     

     

    此图组合关系生成代码与聚合关系代码是一致的。

     

     

    关联包含了组合和聚合,又分单向关联和双向关联;

    依赖:对象作为方法参数,对象作为局部变量,调用类的静态方法。

    看如下代码:

    package s;

     

    //AB之间为聚合关系

    public class A {

     

        private B b;

       

        public A(B b){

           this.b = b;

        }

    }

     

     

    package s;

     

    //CB之间为组合关系

    public class B {

     

        private C c;

        public B(){

           c = new C();

        }

    }

     

     

    package s;

     

    //CD之间为依赖关系

    public class C {

     

        public void method(D d){

           d.m();

        }

    }

     

    package s;

     

    public class D {

     

        public void m(){

          

        }

    }

     

    package s;

     

    import java.util.List;

     

    //ED之间为聚合关系

    public class E {

     

        private List<D> list;

        public void m(){

          

        }

        public List<D> getList() {

           return list;

        }

        public void setList(List<D> list) {

           this.list = list;

        }

    }

     

    package s;

     

    //FE之间为依赖关系

    public class F {

     

       

        public void m(){

           E e = new E();

           e.m();

        }

    }

     

    但生成的类图却是这样:

     

     

     

     

     

     

     

    展开全文
  • UWB模块SKU610 集成了BLE处理器nRF52832和高性能UWB收发器DW1000,内置加速度传感器,实现运动、静止不同状态下的工作模式、定位频率的智能切换。采用BLE处理器nRF52832,使得模块实现超低静态功耗同时还具有BLE功能...
  • 双向DFS

    2021-04-03 10:52:06
    在这种情况下,我们就可以采用双向搜索——从初态和终态出发各搜索一半状态,产生两棵深度减半的搜索树,在中间交会、组合成最终的答案。 如下图所示,左侧是直接进行一次搜索产生的搜索树,右侧是双向搜索的两棵...
  • 思考职责链模式 ①职责链的本质:分离职责,动态组合。分离职责是前提,动态组合才是职责链模式的精华所在,因为这意味着可以很方便地修改和添加新的处理对象,从而让系统更加灵活和具有更好的扩展性。 ②职责链的...
  • <!doctype html> <html > <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title> KNOCKOUT LESSON 4 </title>... ...
  • 双向BFS

    2020-07-03 10:23:47
    双向BFS本质还是bfs,不过是在已知起点和终点的状况下从起点和终点两头开始bfs,这样可以节省时间避免单bfs时所带来的组合爆炸,而且在解决起点和终点均可移动且移动速度不同等鬼畜问题时有奇效 模板 #include<...
  • UWB模块SKU610 集成了BLE处理器nRF52832和高性能UWB收发器DW1000,内置加速度传感器,实现运动、静止不同状态下的工作模式、定位频率的智能切换。采用BLE处理器nRF52832,使得模块实现超低静态功耗同时还具有BLE功能...
  • 尽管从形式上可将双向可控硅看成两只普通可控硅的组合,但实际上它是由7只晶体管和多只电阻构成的功率集成器件。小功率双向可控硅一般采用塑料封装,有的还带散热板。典型产品有BCMlAM(1A/600V)、BCM3AM(3A/600V...
  • 双向绑定

    2018-09-23 20:15:57
    我们看到的网站页面中,是由数据和设计两部分组合而成。将设计转换成浏览器能理解的语言,便是html和css主要做的工作。而将数据显示在页面上,并且有一定的交互效果(比如点击等用户操作及对应的页面反应)则是js...
  • 在UML类图中,类之间的关系可以分成:关联(association)、聚合(aggregation)、组合(composition)、依赖(dependency)、泛化(generalization)/继承(inheritance)和实现(realization)。这六种关系如下图所描绘: &...
  • 三端双向交流开关(TRIAC=TRIode(三端)AC semiconductor switch)实质上是双向晶闸管,它是在...尽管从形式上可以把双向晶闸管看成两只普通晶闸管的组合,但实际上它是由七只晶体管和多只电阻构成的功率集成器件。小...
  • 双向BFS模板

    2018-11-18 20:04:34
    如果已经知道搜索的开始状态和结束状态, 要找一个满足某种条件的一条路径(一般是最短路径),为了避免无谓的“组合爆炸”产生,就可以采取双向广度搜索算法,也就是从开始状态和结束状态同时开始搜索,一个向前搜...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,513
精华内容 605
关键字:

双向组合