zoukankan      html  css  js  c++  java
  • 位向量实现集合—王晓东数据结构

    王晓东数据结构中集合一章,用位向量实现集合看的很懵记录一下。

    N是一个不大的固定整数时,{1,2...N}是N的子集 假如N=10000,可以用数组A[N]来表示这个集合的存在,此时数组大小为A[N],如A[1]=1表示集合中第一个元素存在。

    位向量顾名思义就是用位来存储元素。以书中unsigned short类型为例,下面用US表示。US占位2个字节,16位,那么一个US就可以表示16个数,那么这N个数只需要用N/16 个US类型数表示。此时A数组大小为A[N/16+1],

    A[0]表示1-16个数(0-15)

    A[1]表示2-32个数(16-31)

    ...

    A[0]=13,可看成000000001011,A[0]的第一个位置、第二个位置、第四个位置的数存在,即0、1、3三个数存在。 

    假如输入一个数30,首先先确定在数组哪个位置,30/16=1,此时应在数组A[1]里,计算在A[1]中的位置则只需要30%16+1=15,表示在第15个位置。

    下面解析王晓东书中集合的实现方法:

    集合的基本运算:

    //并集运算:其运算结果为集合A和集合B的并集
    Set SetUnion(Set A,Set B);
    
    //交集运算:其运算结果为集合A和集合B的交集
    Set SetIntersection(Set A,Set B);
    
    //赋值运算:将集合B赋值给A
    void SetAssign(Set A,Set B);
    
    //判断运算:相等返回1 否则返回0
    int SetEqual(Set A,Set B);
    
    //成员运算:x与集合相同的类型,当x属于S时,返回1 否则返回0
    int SetMember(int x,Set set);
    
    //插入运算:将x与插入集合S,当x本身属于S时,不改变集合
    void SetInsert(int x,Set s);
    
    //删除运算:将集合S中的x元素删除,当x不属于S时,不改变集合
    void SetDelete(int x,Set s );

    Set集合定义:

    typedef struct set
    {
        int size;//能存储元素规模
        //数组大小应该看类型 如v为 ushort应该一个数可以存16个 大小为arr/16+1||(size+15)
        int arraysize;
        //向量组 每个向量能存储16个
        unsigned short *v;
    } Bitset, *Set;

    SetInit函数用于创建新Set:

    Set InitSet(int size)
    {
        Set _set = new Bitset;
        _set->size = size;
        //一个US类型可以表示16个 故数组大小为1+size/16
        //书中这种向右移动4位的运算方式等同于/16
        _set->arraysize = (size+15)>>4;
        //书中v大小为size 个人认为有错,有不同意见的朋友欢迎探讨
        _set->v = new unsigned short[_set->arraysize];
        for (int i = 0; i <_set->arraysize; i++) 
    {
    _set
    ->v[i] = 0;
    }
    return _set;
    }

    SetAssign函数用于赋值:

    //把B赋值给A
    void SetAsign(Set A, Set B)
    {
        if (A->size != B->size)
            return;
        for (int i = 0; i < A->size; i++)
        {
            A->v [i] = B->v[i];
        }
    }

    ArrayIndex寻找数在数组中的位置:

    //计算位置大小 除类型的大小 UShort为16 故要/16 按位的话/4即可
    int ArrayIndex(int x){
        return x>>4;
    }

    BitMask函数寻找在US位置中第几位:

    //计算这个数在一个ushort里面所在的第几个位置 除16取余+1即可
    //输入10二进制为1010为15 1111 &计算得1010表示10 之后右移
    unsigned short BitMask(int x){
        return 1<<(x&15);
    }

    SetInsert插入函数:

    //位插入运算 查找数组位置  找到x%16放置 用|运算
    //如17插入,此时数组v[1]中为00100000,表示第七个位置有东西,17%16+1=2 |运算后v[1]为00100010
    void SetInsert(int x,Set s){
        if(x<0||s->size<x)
            return;
        s->v[ArrayIndex(x)]|=BitMask(x);
    }

    SetDelete删除函数:

    //删除元素运算 先取反再去取&
    //如删除17,此时数组v[1]中为00100010,表示第2、7个位置有东西,17%16+1=2 ~2取反为11111101 &运算后v[1]为00100000
    void SetDelete(int x,Set s ){
         if(x<0||s->size<x)
            return;
         s->v[ArrayIndex(x)]&=~BitMask(x);
    }

    SetMember函数查看元素是否存在:

    //检测元素是否存在
    int SetMember(int x,Set set){
        if(x<0||x>set->size)
            return 0;
        //首先查找数组对应位置,与x相对的位置
        //如3 此时在数组第一个位置 BitMask值为1000 表示第4数,第1个为0
        return set->v[ArrayIndex(x)]&BitMask(x);
    }

    SetEqual函数判断集合A和B是否相等:

    int SetEqual(Set A,Set B){
        if(A->size! B->size)
            return 0;
        for (int i = 0; i < A->arraysize; i++)
        {
            if(A->v[i]! B->v[i])
                return 0;
        }
        return 1;
    }

    SetUnion并集运算:

    //取并集  如A=1100 B=0110 此时第2、3、4个为并集
    Set SetUnion(Set A,Set B){
        Set s=InitSet(A->size);
        for (int i = 0; i < s->arraysize; i++)
        {
            //按位|
            s->v[i]=A->v[i] B->v[i];
        }
    }

    SetIntersection交集运算:

    //取交集  如A=1100 B=0100=>0100 此时第3个为交集
    Set SetIntersection(Set A,Set B){
        Set s=InitSet(A->size);
        for (int i = 0; i < s->arraysize; i++)
        {
            //按位&
            s->v[i]=A->v[i] B->v[i];
        }
    }

    SetDifference差集运算:

    //取差集  如A=111000 B=001000=>取&为001000 再异或110000 此时第5.6个为差集
    Set SetDifference(Set A,Set B){
        Set s=InitSet(A->size);
        for (int i = 0; i < s->arraysize; i++)
        {
            //按位& 再^
            s->v[i]=A->v[i]^(A->v[i]&B->v[i]);
        }
    }
  • 相关阅读:
    NSlog 对于新手的一点技巧和用法.
    iOS7+ 扫描二维码和条形码实现 耗时操作
    关于iOS block循环引用的一点理解
    Xcode 快捷开发的几个插件
    在Mac下面删除所有的.svn文件
    一个textView 预留空白的问题
    Supporting Multiple iOS Versions and Devices
    Building an iOS Universal Static Library
    iOS Library With Resources
    iOS开发长文--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总
  • 原文地址:https://www.cnblogs.com/dlvguo/p/11516412.html
Copyright © 2011-2022 走看看