Basic-Computer-Science:Lab 1 Set ( 计算机科学基础 )

Basic Computer Science – Learning set and implement the required methods specified in the lab specification.

这是计算机科学基础课程中的第一个实验,主要是借助计算机语言来进行set(集合)的各种操作。

为了达到实验效果,在该实验中禁止使用STL容器。

Analysis

由于集合的特点是 unordered and no duplicated(无序并且不重复),我们可以通过以下两种方式实现set。

不同的方法时间复杂度和空间复杂度有较大差异,但是由于Lab的测试样例太小,因此在此处两种方式并无显著差异。

Method 1

通过顺序遍历的方式剔除数组中的重复元素,最终剩余的元素即为set。

该方法较好的模拟了剔除元素的过程,但是对于集合的其他操作如equalsubsetunionintersetion等,该方法时间复杂度会更高。

Make Set

朴素方法剔除重复元素时间复杂度为O(n^2),空间复杂度为O(n),这也是建立一个set的成本。

for(int i=0;i<len-1;i++)
{
	for(int j=i+1;j<len;j++)
	{
		if(str[i]==str[j])
		{
			for(int k=j;k<len;k++)
			{
				str[k]=str[k+1];
			}
			len--;
			j--;
		}
	}
}

Equal

判断是否相等。可以直接判断两个set中元素是否相同,朴素的查找最坏情况时间复杂度是O(n^2),我们也可以通过sort()和strcmp()函数降低时间复杂度和代码难度

char set1[100],set2[100];

sort(set1,set1+strlen(set1));
sort(set2,set2+strlen(set2));

if(!strcmp(set1,set2))
{
	cout<<"Equal!";
}else cout<<"Not equal!";

在c++中可以直接使用string类做字符串,string支持“=”运算符,无需借助函数。

Subset

判断子集。不能直接借助strcmp函数,因为strcmp是按照字典序返回大小,与两集合中元素是否重复无关。

朴素判断的时间复杂度为O(mn)

char set1[100],set2[100];
int len1=strlen(set1);
int len2=strlen(set2);
bool flag=1;
for(int i=0;i<len1;i++)
{
	bool f=0;
	for(int j=0;j<len2;j++)
	{
		if(set1[i]==set2[j])
		{
			f=1;
			break;
		}
	}
	if(f) continue;
	else {
		flag=0;
		break;
	}
}
if(flag) cout<<"A is a subset of B";
else cout<<"A is not a subset of B";

Union

求并集。我们可以通过连接两个set形成一个字符串,然后对新字符串进行make set操作,即可得到一个Union。

这样的时间复杂的约为make set的时间复杂度O((m+n)^2)

或者是朴素算法遍历两个数组,时间复杂度为O(mn)

char set1[100],set2[100];
char set3[100];
int len1=strlen(set1);
int len2=strlen(set2);
strcpy(set3,set2);
int len3=strlen(set3);
bool flag=1;
for(int i=0;i<len1;i++)
{
	bool f=0;
	for(int j=0;j<len2;j++)
	{
		if(set1[i]==set2[j])
		{
			f=1;
			break;
		}
	}
	if(f) continue;
	else {
		set3[len3++]=set1[i];
	}
}

另一种思路是使用two_point(前提是set经过了排序),然后使用类似归并排序的方式创建新集合,这里不在赘述。

时间复杂度为O(m+n)+O(log n)(排序的时间)

Intersetion

求交集。朴素算法仍为 O(mn)

char set1[100],set2[100];
char set3[100];
int tot=0;
cin>>set1;
cin>>set2;
int len1=strlen(set1);
int len2=strlen(set2);
for(int i=0;i<len1;i++)
{
	for(int j=0;j<len2;j++)
	{
		if(set1[i]==set2[j])
		{
			set3[tot++]=set1[i];
			break;
		}
	}	
}
set3[tot]='\0';

Method 2

通过计数排序统计出现的元素,最后遍历计数数组,若非0则代表当前key是set的元素。

该方法除Make Set外,其他操作时间复杂度均为O(1).

Make Set

时间复杂度为O(n),空间复杂度为2*n;

但我们可以通过二进制状态压缩实现空间复杂度的优化,

void make_set()
{
	cin>>input;
	if(input==empty_set) return ;
	int len=input.size();
	for(int i=0;i<len;i++)
	{
		if(input[i]==',') continue;
		if(!new_set[input[i]])
		{
			new_set[input[i]]=1;
		}
	}
	return ;
}

Equal

bool check_equal()
{
	for(int i=0;i<256;i++)
	{
		if(set1[i]!=set2[i])
		{
			return 0;
		}
	}	
	return 1;
}

Subset

 
bool check_subset()
{
	for(int i=0;i<256;i++)
	{
		if(set1[i]==1&&set2[i]==0)
		{
			return 0;
		}
	}	
	return 1;
}

Union

 
void union_set()
{
	for(int i=0;i<256;i++)
	{
		set1[i]+=set2[i];
	}
	return ;
}

Intersetion

 
void make_intersetion()
{
	for(int i=0;i<256;i++)
	{
		intersetion[i]=set1[i]&&set2[i];
	}
	return ;
}

Example

以下给出该实验的几个实例,实现方式采用Method 2.

Task1

Write a method to produce a set from the input. (note: elements in the set are unordered, and no duplicated elements).

#include<bits/stdc++.h>
using namespace std;

int new_set[256]={0};
string input;
string empty_set="\\n";

void make_set()
{
	cin>>input;
	if(input==empty_set) return ;
	int len=input.size();
	for(int i=0;i<len;i++)
	{
		if(input[i]==',') continue;
		if(!new_set[input[i]])
		{
			new_set[input[i]]=1;
		}
	}
	return ;
}

void out_set()
{
	bool f=0;
	for(int i=0;i<256;i++)
	{
		if(new_set[i]) 
		{
			if(f)
			printf(",%c",i);
			else {
				f=1;
				printf("{%c",i);
			}
		}
		if(i==255&&f) cout<<"}";
	}
	if(f==0) cout<<"The set is empty!";
	return ;
}

void rec()
{
	memset(new_set,0,sizeof new_set);
}

int main()
{
	rec();
	make_set();
	out_set();
	return 0;
}

Task2

Given two sets, write a method to check if the two sets are equal

#include<bits/stdc++.h>
using namespace std;

int new_set[2][256];
string input;
string empty_set="\\n";

void make_set(int n)
{
	cin>>input;
	if(input==empty_set) return ;
	int len=input.size();
	for(int i=0;i<len;i++)
	{
		if(input[i]==',') continue;
		if(!new_set[n][input[i]])
		{
			new_set[n][input[i]]=1;
		}
	}
	return ;
}

bool check_equal()
{
	for(int i=0;i<256;i++)
	{
		if(new_set[0][i]!=new_set[1][i])
		{
			return 0;
		}
	}	
	return 1;
}

void rec()
{
	memset(new_set,0,sizeof new_set);
}

int main()
{
	rec();
	for(int i=0;i<2;i++)
	{
		make_set(i);
	}
	if(check_equal())
	{
		cout<<"Equal.";
	}else cout<<"Not equal.";
	return 0;
}

Task3

Given two inputs, A and B, write a method to check if the A is a subset of the B.

#include<bits/stdc++.h>
using namespace std;

int new_set[2][256];
string input;
string empty_set="\\n";

void make_set(int n)
{
	cin>>input;
	if(input==empty_set) return ;
	int len=input.size();
	for(int i=0;i<len;i++)
	{
		if(input[i]==',') continue;
		if(!new_set[n][input[i]])
		{
			new_set[n][input[i]]=1;
		}
	}
	return ;
}

bool check_subset()
{
	for(int i=0;i<256;i++)
	{
		if(new_set[0][i]==1&&new_set[1][i]==0)
		{
			return 0;
		}
	}	
	return 1;
}

void rec()
{
	memset(new_set,0,sizeof new_set);
	return ;
}

int main()
{
	rec();
	for(int i=0;i<2;i++)
	{
		make_set(i);
	}
	if(check_subset())
	{
		cout<<"A is a subset of the B.";
	}else cout<<"A is not a subset of the B.";
	return 0;
}

Task4

Given two inputs, write a method to output the set union of these inputs.

#include<bits/stdc++.h>
using namespace std;

int new_set[2][256];
string input;
string empty_set="\\n";

void make_set(int n)
{
	cin>>input;
	if(input==empty_set) return ;
	int len=input.size();
	for(int i=0;i<len;i++)
	{
		if(input[i]==',') continue;
		if(!new_set[n][input[i]])
		{
			new_set[n][input[i]]=1;
		}
	}
	return ;
}

void union_set()
{
	for(int i=0;i<256;i++)
	{
		new_set[0][i]+=new_set[1][i];
	}
	return ;
}

void out_set()
{	
	bool f=0;
	for(int i=0;i<256;i++)
	{
		if(new_set[0][i]) 
		{
			if(f)
			printf(",%c",i);
			else {
				f=1;
				printf("{%c",i);
			}
		}
		if(i==255&&f) cout<<"}";
	}
	if(f==0) cout<<"The set is empty!";
	return ;
}

void rec()
{
	memset(new_set,0,sizeof new_set);
	return ;
}

int main()
{
	rec();
	for(int i=0;i<2;i++)
	{
		make_set(i);
	}
	union_set();
	out_set();
	return 0;
}

Task5

Given two inputs, write a method that will output the set intersection of these inputs.

#include<bits/stdc++.h>
using namespace std;

int new_set[2][256];
int intersetion[256];
string input;
string empty_set="\\n";

void make_set(int n)
{
	cin>>input;
	if(input==empty_set) return ;
	int len=input.size();
	for(int i=0;i<len;i++)
	{
		if(input[i]==',') continue;
		if(!new_set[n][input[i]])
		{
			new_set[n][input[i]]=1;
		}
	}
	return ;
}

void make_intersetion()
{
	for(int i=0;i<256;i++)
	{
		intersetion[i]=new_set[0][i]&&new_set[1][i];
	}
	return ;
}

void out_set()
{	
	bool f=0;
	for(int i=0;i<256;i++)
	{
		if(intersetion[i]) 
		{
			if(f)
			printf(",%c",i);
			else {
				f=1;
				printf("{%c",i);
			}
		}
		if(i==255&&f) cout<<"}";
	}
	if(f==0) cout<<"The set is empty!";
	return ;
}

void rec()
{
	memset(new_set,0,sizeof new_set);
	return ;
}

int main()
{
	rec();
	for(int i=0;i<2;i++)
	{
		make_set(i);
	}
	make_intersetion();
	out_set();
	return 0;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇