【C言語】2つの配列の和集合を求めるプログラムの書き方と解説
和集合(union)とは、2つの集合に含まれるすべての要素を重複なくまとめたものです。C言語では、この和集合演算を配列を使って簡単に実装できます。本記事では、2つの整数型配列の和集合を求めるCプログラムを、アルゴリズムの考え方から実際の実行結果まで、初心者にもわかりやすく解説します。
和集合演算とは
たとえば、次のような2つの配列を考えてみましょう。
- 配列1 = {1, 2, 3, 4, 6}
- 配列2 = {1, 2, 5, 6, 7}
この2つの配列の和集合は、次のように表されます。
配列1 ∪ 配列2 = {1, 2, 3, 4, 6} ∪ {1, 2, 5, 6, 7}
= {1, 2, 3, 4, 5, 6, 7}
つまり、両方の配列に現れるすべての要素を集め、重複する値を1つにまとめた集合が和集合です。
和集合を求めるロジック
1. 2つの配列を1つに連結する
まず、配列aの全要素と配列bの全要素を、新しい配列uniに順番にコピーします。
for(i=0;i<size1;i++){
uni[j]=a[i];
j++;
}
for(i=0;i<size2;i++){
uni[j]=b[i];
j++;
}
2. 重複した要素を削除する
次に、連結した配列内の重複要素を取り除きます。各要素について、それ以降の要素と比較し、同じ値が見つかれば後ろの要素を前に詰めて削除していきます。
int removerepeated(int size,int a[]){
int i,j,k;
for(i=0;i<size;i++){
for(j=i+1;j<size;){
if(a[i]==a[j]){
for(k=j;k<size;k++){
a[k]=a[k+1];
}
size--;
}else{
j++;
}
}
}
return(size);
}
完全なCプログラム
以下が、2つの配列に対して和集合演算を実行するCプログラムの全体像です。処理の流れは「入力 → 連結 → ソート → 重複削除 → 出力」となっています。
#include<stdio.h>
int removerepeated(int size,int a[]);
void sort(int size,int a[]);
main(){
int i,size1,size2,size,j=0,k;
printf("Enter size of an array1\n");
scanf("%d",&size1);
printf("Enter size of an array2\n");
scanf("%d",&size2);
int a[size1],b[size2],uni[size1+size2];
printf("Enter numbers for array 1\n");
for(i=0;i<size1;i++){
scanf("%d",&a[i]);
}
printf("Enter numbers for array 2\n");
for(i=0;i<size2;i++){
scanf("%d",&b[i]);
}
/* 和集合の開始 */
for(i=0;i<size1;i++){
uni[j]=a[i];
j++;
}
for(i=0;i<size2;i++){
uni[j]=b[i];
j++;
}
/* ソート */
sort(size1+size2,uni);
/* 重複要素の削除 */
size=removerepeated(size1+size2,uni);
printf("Array after Union \n");
for(i=0;i<size;i++){
printf("%d\n",uni[i]);
}
}
int removerepeated(int size,int a[]){
int i,j,k;
for(i=0;i<size;i++){
for(j=i+1;j<size;){
if(a[i]==a[j]){
for(k=j;k<size;k++){
a[k]=a[k+1];
}
size--;
}else{
j++;
}
}
}
return(size);
}
void sort(int size,int a[]){
int i,j,temp;
for(i=0;i<size;i++){
for(j=i+1;j<size;j++){
if(a[i]>a[j]){
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
}
実行結果
上記のプログラムをコンパイルして実行すると、次のような出力が得られます。配列1に{1, 2, 3, 4}、配列2に{3, 5, 6}を入力した場合、共通する「3」が1つにまとめられ、和集合として{1, 2, 3, 4, 5, 6}が出力されます。
Enter size of an array1
4
Enter size of an array2
3
Enter numbers for array 1
1
2
3
4
Enter numbers for array 2
3
5
6
Array after Union
1
2
3
4
5
6
補足:計算量と改良のポイント
このプログラムでは、ソートと重複削除のどちらも二重ループを使用しているため、計算量はO(n²)となります。そのため、要素数が多いデータを扱う場合は、標準ライブラリのqsort関数による高速なソートや、ハッシュテーブルを利用した重複管理を検討すると効率的です。
また、サンプルコードでは可変長配列(VLA)を使用しています。これはC99以降でサポートされる機能なので、古いコンパイラを使用する場合は注意が必要です。さらに、main関数は戻り値の型を明示して「int main(void)」と宣言し、最後に「return 0;」を返すのが現代的なC言語の作法として推奨されます。
-
C++で3次元空間における2つの平面間の角度を計算する方法
本記事では、3次元空間内にある2つの平面 P1 と P2 の間の角度を求める方法を解説します。平面の方程式と角度の公式平面 Pi の方程式は、一般に次の形式で表されます。a・x + b・y + c・z + d = 0ここで、係数 (a, b, c) は平面の法線ベクトルを表しています。2つの平面がなす角度を「A」とすると、それぞれの法線ベクトルのなす角として、次の式で求められます。cos A = (a₁a₂ + b₁b₂ + c₁c₂) / (√(a₁² + b₁² + c₁²) × √(a₂² + b₂² + c₂²))つまり、分子は2つの法線ベクトルの内積、分母はそれぞれの法線ベクトルの大
-
PythonでExcelスプレッドシートの数式を計算するプログラムの作成方法
2次元の行列がExcelスプレッドシートを表していると仮定します。このとき、すべてのセルと数式を計算し終えた状態の同じ行列を求める必要があります。Excelスプレッドシートは一般的に以下のような構造を持っています。B17035=A1+A2列には「A、B、C…」、行には「1、2、3…」という名前が付けられています。各セルには、値そのもの、別のセルへの参照、あるいは数値やセル参照を使った演算を表すExcel数式のいずれかが格納されます(例:「=A1+5」「=A2+B2」「=2+5」など)。入力と出力の例たとえば、入力が以下のような場合を考えてみましょう。B17035=A1+A2このとき、期待される