Set:
简单的资料结构
程度★ 难度★
简单的资料结构
set 是指数学名词「集合」。在这里我们只考虑元素为整数的集合。「集合」有几点特性:
一、空集合。
二、集合中的元素不会重复。
要表达一个集合,可以直观的用一条一维的int 阵列:将集合里的所有元素,依序放进阵列中。再用一个变数,纪录元素总数。
- struct Set
- {
- int array [ 1000 ]; //可存入1000个元素
- int num ; //纪录集合中有多少元素
- };
这样就能存入1000 个元素。
然而,以这种资料结构,做联集、交集、差集之类的运算,则会相当麻烦,也会比较慢。
【待补程式码】【待补link list 的纪录法】
UVa 496
Set:
另一种资料结构
程度★ 难度★
另一种资料结构
另外一种表达集合的方法,是用一条一维的bool 阵列:集合里若有x 这个元素,就让array[x] 这个位置为true ,反之则为false 。其概念类似于数学领域提到的Index Set 。
它的坏处就是数值有界限、受阵列大小影响。但是,以这种资料结构,做联集、交集、差集之类的运算,则会比较快,时间复杂度为O( 元素总个数) 。
- bool set [ 1000 ]; //一个集合,元素的数值范围为0到999
- // 加入元素
- void add_element ( bool a [ 1000 ], int element)
- {
- a [ element ] = true ;
- }
- // 除去元素
- void delete_element ( bool a [ 1000 ], int element )
- {
- a [ element ] = false ;
- }
- // 联集
- void union ( bool a [ 1000 ], bool b [ 1000 ], bool c [ 1000 ])
- {
- for ( int i = 0 ; i < 1000 ; i ++) c [ i ] = a [ i ] || b [ i ];
- }
- // 交集
- void intersection ( bool a [ 1000 ], bool b [1000 ], bool c [ 1000 ])
- {
- for ( int i = 0 ; i < 1000 ; i ++) c [ i ] = a [ i ] && b [ i ];
- }
- // 差集
- void difference ( bool a [ 1000 ], bool b [ 1000], bool c [ 1000 ])
- {
- for ( int i = 0 ; i < 1000 ; i ++) c [ i ] = a [ i ] && ! b [ i ];
- }
- // 补集
- void complement ( bool a [ 1000 ], bool b [ 1000])
- {
- for ( int i = 0 ; i < 1000 ; i ++) b [ i ] = ! a [ i ];
- }
- // 判断是否为空集合
- bool empty ( bool a [ 1000 ])
- {
- for ( int i = 0 ; i < 1000 ; i ++)
- if ( a [ i ])
- return false ;
- return true ;
- }
- // 判断是否没有交集
- bool disjoint ( bool a [ 1000 ], bool b [ 1000])
- {
- for ( int i = 0 ; i < 1000 ; i ++)
- if ( a [ i ] && b [ i ])
- return false ;
- return true ;
- }
- // 判断a有没有包含b
- bool contain ( bool a [ 1000 ], bool b [ 1000 ])
- {
- for ( int i = 0 ; i < 1000 ; i ++)
- if (! a [ i ] && b [ i ])
- return false ;
- return true ;
- }
这里是练习题。
Set:
Bit Array
程度★ 难度★
Bit Array ( Bitset )
还有一种方法,是用bit 来代替bool 变数。在电脑当中,一个bit 只有0 和1 两种值,类似于bool 变数,两者都可以用来表示一个集合元素存不存在。利用bit 们来表达集合,可以节省储存空间,也可以节省运算时间。
一个int 变数所使用的记忆体大小为32bit ,可以当作是32 个数字的集合。需要更多bit 的话,就开一条阵列吧!
- typedef int Bitset [ 100 ]; //一个集合,元素的数值范围为0到3199
- // 求出element所在的阵列格子,即是element除以32的商数
- int get_pos ( int element )
- {
- return element >> 5 ;
- }
- // 求出element在阵列格子当中是第几个bit,即是element除以32的余数
- // 然后让一个bit位移至适当位置,以利计算
- int get_bit ( int element )
- {
- return 1 << ( element & 31 );
- }
- // 加入元素
- void add_element ( Bitset a , int element )
- {
- a [ get_pos ( element )] |= get_bit ( element);
- }
- // 除去元素
- void delete_element ( Bitset a , int element )
- {
- a [ get_pos ( element )] &= ~ get_bit ( element);
- }
- // 联集
- void union ( Bitset a , Bitset b , Bitset c )
- {
- for ( int i = 0 ; i < 100 ; i ++) c [ i ] = a [ i ] | b [ i ];
- }
- // 交集
- void intersection ( Bitset a , Bitset b , Bitset c )
- {
- for ( int i = 0 ; i < 100 ; i ++) c [ i ] = a [ i ] & b [ i ];
- }
- // 差集
- void difference ( Bitset a , Bitset b , Bitset c )
- {
- for ( int i = 0 ; i < 100 ; i ++) c [ i ] = a [ i ] & ~ b [ i ];
- }
- // 补集
- void complement ( Bitset a , Bitset b )
- {
- for ( int i = 0 ; i < 100 ; i ++) b [ i ] = !a [ i ];
- }
- // 判断是否为空集合
- bool empty ( Bitset a )
- {
- for ( int i = 0 ; i < 100 ; i ++)
- if ( a [ i ])
- return false ;
- return true ;
- }
- // 判断是否没有交集
- bool disjoint ( Bitset a , Bitset b )
- {
- for ( int i = 0 ; i < 100 ; i ++)
- if ( a [ i ] & b [ i ])
- return false ;
- return true ;
- }
- // 判断a有没有包含b
- bool contain ( Bitset a , Bitset b )
- {
- for ( int i = 0 ; i < 100 ; i ++)
- if (~ a [ i ] & b [ i ])
- return false ;
- return true ;
- }