集合是具有共同性质的一组数据构成的整体,集合中的数据叫做集合元素,简称元素。例如,10以内的所有质数构成一个集合,它包括2、3、5、7共4个元素,其共同性质是:是质数并且不大于10。不包括任何元素的集合叫做空集。
集合有以下基本性质:
1、元素唯一性:集合中不存在重复的元素,即每个元素都是唯一的。
2、元素无序性:集合中的元素是没有排列顺序的。
Pascal语言的集合类型有以下限制:
1、集合的元素必须是有序类型的数据。
2、集合的元素数目不能超过256个。
一、集合的定义
type
集合类型名=set of 基类型;
其中,集合类型名是一个合法的标识符,基类型是集合中的元素的类型,它必须是有序类型或有序类型的子界类型,元素的序号范围必须在0至255之间,因此基类型不能是短整型、整型或长整型。
例如:
type
t1=set of 1..5; {基类型是子界类型,元素范围是1到5的整数}
t2=set of char; {基类型是字符型,元素范围是全体字符}
t3=set of (white,red,blue,black); {基类型是枚举类型}
定义了集合类型之后,就可以用类型标识符来定义变量了,定义集合变量的格式为:
var
集合变量名:集合类型名;
例如:
var
a:t1;
Pascal语言允许将集合类型描述和变量定义合并在一起,其格式为:
var
集合变量名:set of 基类型;
例如:
var
a:set of 1..5;
以下集合类型的定义是错误的:
type
t1=set of integer; {整型的元素超过了256个}
t2=set of -30..-20; {元素序号超出了0到255范围}
t3=set of real; {实型不是有序类型}
二、集合的操作
1、集合类型的数据可以进行赋值
例如:
var
a:set of 0..255;
begin
a:=[2,3,5,7];
2、集合类型的数据不能用read和write语句直接输入输出,如果需要输入或输出集合的元素,必须借助集合的运算来实现。
例1:从键盘上输入10个数,添加到集合中,然后输出集合的全部元素。
var
s:set of 0..255;
i,n:byte;
begin
s:=[];
for i:=1 to 10 do begin
read(n);
s:=s+[n];
end;
for i:=0 to 255 do
if i in s then write(i,' ');
end.
3、元素与集合之间可以进行“属于”运算,运算符为in,运算结果为布尔值。对于一个元素x和集合A,若x是A的元素,则称“x属于A”,表达式x in A的值为真;若x不是A的元素,则称“x不属于A”,表达式x in A的值为假。
例如:
1 in [1,2,3] 的值为真
1 in [2,3,4] 的值为假
4、集合之间可以进行并、差、交三种集合运算:
+(集合并)——产生一个包含两个集合元素的集合;
-(集合差)——产生一个包含所有属于第一个集合,但不属于第二个集合的元素的集合;
*(集合交)——产生一个只包含两个集合的公共元素的集合;
例如:
[1,2]+[5,6,7]=[1,2,5,6,7]
[1,2]+[1,2,3,4]=[1,2,3,4]
[1,2,3]-[2]=[1,3]
[1,2,3]-[4]=[1,2,3]
[1,2,3]-[]=[1,2,3]
[1,2,3]*[2,3,4]=[2,3]
[1,2,3]*[4,5]=[]
5、集合之间可以进行“相等”和“包含”两种关系运算,运算结果为布尔值。
若两个集合的所有元素都相同,则这两个集合是相等的。
若集合B的所有元素都是集合A中的元素,则有A>=B,即B<=A。
例如:
[1,2]=[1,2] 的值为真
[1,2]=[1,3] 的值为假
[1,2,3]>=[1,2] 的值为真
[1,2]>=[1,2,3] 的值为假
例2:编写一个加密程序将一个英文句子加密后输出。加密译码规则为:
A、由键盘输入英文句子和密钥M(20<=M<=50)
B、将其中的英文字符都变为大写,用数字1..26分别代表'A'..'Z'并加上密钥M后输出
C、将其中的空格用数字'0'输出
D、其它符号则变成ASCII序号加上100输出
E、输出数字之间用空格分隔
var
st:string;
m,i:byte;
c:char;
begin
write('Input a sentence: ');
readln(st);
repeat
write('Input M: ');
readln(m);
until m in [20..50];
for i:=1 to length(st) do
if st[i] in ['a'..'z','A'..'Z'] then begin
c:=upcase(st[i]);
write(ord(c)-64+m,' ');
end else if st[i]=' ' then write(0,' ')
else write(ord(st[i]+100,' '));
end.
例3:用筛选法求2至100中的所有质数。
分析:筛选法是比较常用的求质数的算法之一,适用于求2到一个给定的上限n之间的全体质数,基本思想是:
1、设立一个2到n之间的全体整数的集合sieve,作为筛选的“原材料”
2、设立一个集合primes,用于存放筛选出来的质数,其初始状态为空
3、i从集合sieve中最小的质数2开始
4、先将i添加到primes中,然后将i的所有整倍数(包括i本身)从sieve中删除,此时sieve中剩下的最小元素x一定是与i紧邻的质数
5、将i更新为x
6、重复执行第4、5步,直到sieve中没有元素为止,此时primes中存放的就是筛选出来的2到n之间的全体质数
const
n=100;
var
sieve,primes:set of 2..n;
p,d:byte;
begin
sieve:=[2..n];
primes:=[];
p:=1;
repeat
repeat
p:=p+1;
until p in sieve;
primes:=primes+[p];
d:=p;
repeat
sieve:=sieve-[d];
d:=d+p;
until d>n;
until sieve=[];
for d:=2 to n do
if d in primes then write(d:4);
end.
例4:将十进制整数k转换成二进制数。以集合类型表示一个32位二进制数,如18的二进制数为10010,则集合中记为[2,5], 即表示第2位、第5位是1,其余都是0。最后再以标准的二进制数输出。
var
buf:set of 1..32;
i,k:longint;
begin
write('Input N= ');
readln(k);
buf:=[];
i:=1;
while k>0 do begin
if k mod 2=1 then buf:=buf+[i];
i:=i+1;
k:=k div 2;
end;
k:=32;
while not (k in buf) do k:=k-1;
for i:=k downto 1 do
if i in buf then write(1)
else write(0);
end.
例5:将1,2,……9这9个数分成三组,分别组成三个三位数,且使这三个三位数构成1:2:3的比例,例如:三个三位数192,384,576满足以上条件,试求出所有满足条件的三个三位数。
var
a,b,c,d,e,f,g,h,n:byte;
i,j,k:integer;
procedure num(x:integer;var u,v,w:byte);
begin
u:=x div 100;
v:=x mod 100 div 10;
w:=x mod 10;
end;
begin
for i:=123 to 329 do begin
j:=2*i;k:=3*i;
num(i,a,b,c);
num(j,d,e,f);
num(k,g,h,n);
if [a,b,c,d,e,f,g,h,n]=[1..9] then writeln(i:5,j:5,k:5);
end;
end.