1. 程式人生 > 其它 >集合運算(整數區間) C實現

集合運算(整數區間) C實現

技術標籤:C

整數區間的集合運算

摘要

最近寫專案程式碼裡用到很多整數區間運算,呼叫頻率很高,想著網上有沒有好的封裝借鑑一下。奈何一頓搜尋猛如虎,合用封裝基本無。不如自己寫一個了。

  • 交集:先用 overlap() 判斷一些區間是否有重疊,然後求出重疊部分即可;
  • 差集:先求交集,然後再減去交集。

話不多說,直接上程式碼,備註完善,測試可用。

程式碼

#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

#define LEFT(p) (p[0])
#define
RIGHT(p) (p[1])
int max(int x, int y) { return x > y ? x : y; } int min(int x, int y) { return x > y ? y : x; } /** * @brief 判斷兩個整數區間是否重疊 * @param x 區間: [x[0], x[1]] * @param y 區間: [y[0], y[1]] * @return true 重疊; false 不重疊 */ bool overlap(const int* x, const int* y) { if (!x || !y) return
false; int begin = max(LEFT(x), LEFT(y)); int end = min(RIGHT(x), RIGHT(y)); return end - begin >= 0; } /** * @brief 交集(整數區間) * @param x 區間: [x[0], x[1]] * @param y 區間: [y[0], y[1]] * @param is 所求交集 * @return true 有交集; false 無交集 */ bool intersection(const int* x, const int* y, int
* is) { if (overlap(x, y)) { LEFT(is) = max(LEFT(x), LEFT(y)); RIGHT(is) = min(RIGHT(x), RIGHT(y)); return true; } return false; } /** * @brief 差集(整數區間): 屬於x但不屬於y 區間合法性由呼叫者保證 * @param x 區間: [x[0], x[1]] * @param y 區間: [y[0], y[1]] * @param ds 差集區間 * @param n 返回的差集數量 */ void differenceSet(const int* x, const int* y, int ds[][2], int* n) { int is[2]; int c = 0; if (intersection(x, y, is)) { if (LEFT(is) > LEFT(x)) { LEFT(ds[c]) = LEFT(x); RIGHT(ds[c]) = LEFT(is) - 1; c++; } if (RIGHT(is) < RIGHT(x)) { LEFT(ds[c]) = RIGHT(is) + 1; RIGHT(ds[c]) = RIGHT(x); c++; } } else { LEFT(ds[c]) = LEFT(x); RIGHT(ds[c]) = RIGHT(x); c = 1; } *n = c; } /** * @brief 集合運算(整數區間) * 區間有效性由呼叫者保證: 有效區間 x 滿足 LEFT(x) <= RIGHT(x) */ int main() { int x[2]; int y[2]; int is[2]; // 存放所求得的交集 int ds[2][2]; // 存放所求得的差集 int n; // 差集數量,0 ~ 2 printf("請輸入整數區間x: "); scanf("%d %d", &LEFT(x), &RIGHT(x)); assert(LEFT(x) <= RIGHT(x)); printf("請輸入整數區間y: "); scanf("%d %d", &LEFT(y), &RIGHT(y)); assert(LEFT(y) <= RIGHT(y)); // 交集 intersection(x, y, is) ? printf("交集: [%d %d]\n", LEFT(is), RIGHT(is)) : printf("不相交\n"); // 差集 differenceSet(x, y, ds, &n); switch (n) { case 0: printf("差集為空(區間 y 包含區間 x)\n"); break; case 1: printf("差集: [%d %d]\n", LEFT(ds[0]), RIGHT(ds[0])); break; case 2: printf("差集: [%d %d] + [%d %d]\n", LEFT(ds[0]), RIGHT(ds[0]), LEFT(ds[1]), RIGHT(ds[1])); break; default: break; } }

測試

# 生成測試檔案 a.out
gcc interval.c
$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 1 4
不相交
差集: [5 9]

$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 10 19
不相交
差集: [5 9]

$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 5 9
交集: [5 9]
差集為空(區間 y 包含區間 x)

$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 5 6
交集: [5 6]
差集: [7 9]

$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 6 9
交集: [6 9]
差集: [5 5]

$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 4 10
交集: [5 9]
差集為空(區間 y 包含區間 x)

$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 4 8
交集: [5 8]
差集: [9 9]

$ ./a.out 
請輸入整數區間x: 5 9
請輸入整數區間y: 6 560
交集: [6 9]
差集: [5 5]