演算法:如何使用C++實現一個簡單的集合類
來自於C++程式設計的一個題目。實現一個集合類,要求實現以下4個操作。
- 向集合中新增元素,如果集合中已存在元素則不新增
- 從集合中移除元素,移除之前需要先判斷集合中元素是否存在
- 過載
+
運算子,用以實現集合的求並集運算 - 過載
*
運算子,用以實現集合的求交集運算
1.類的整體設計
該問題需要模擬實現集合類,我們可以使用陣列來模擬集合,於是使用int items[100]
用來存放集合中的資料。為了實現陣列的遍歷,這就需要一個整數用來表示陣列中元素的個數,於是使用int number
來表示陣列中元素的個數;此外,為了實現題目的需求,設計以下四個函式:
- 使用
add_item(int item)
成員函式向陣列中新增元素 - 使用
remove_item(int item)
成員函式向陣列中移除元素 - 過載
operator+
表示集合的求並集運算 - 過載
operator*
表示集合的求交集運算
由於向集合新增元素之前,必須確保集合中不存在該元素;在從集合中移除元素之前,必須確保集合中存在該元素,因此新增is_exist(int item)
方法用以判斷集合中是否存在這個元素;此外為了顯示集合,新增display()
方法, 基本設計如下:
class Set { public: int items[100]; //定義一個陣列作為容器存放100個集合元素 int number; //定義數字i表示集合中元素的個數 //建構函式和解構函式 Set() { this->number = 0; memset(this->items,0,sizeof(items)); } //初始化方法 int init(int items[], int num); //新增元素 bool add_item(int item); //刪除元素 bool remove_item(int item); //求集合的並集 Set operator+ (Set set2); //求集合的交集 Set operator* (Set set2); //顯示集合元素 int display(); //判斷集合當中是否存在item,返回元素在集合中的位置,不存在返回-1 int is_exist(int item); };
2.建構函式
Set() { this->number = 0; memset(this->items,0,sizeof(items)); }
在建構函式中,我們對陣列進行初始化,宣告完陣列之後,如果不進行初始化,陣列元素是隨機值,在C語言中,變數不進行初始化都會被分配隨機值。為了避免這種情況,我們使用memset函式對陣列items所有元素全部賦值為0;同時,由於此時陣列中沒有元素,即元素個數為0,我們的number也應當賦值為0.
3.判斷陣列中是否包含元素 item
int Set::is_exist(int item) { for(int i=0; i< this->number; i++) { if(this->items[i] == item) { return i; } } return -1; }
該函式用於判斷陣列中是否存在item元素,如果存在就返回item元素的位置,如果不存在就返回-1. 判斷方法非常簡單,寫一個for迴圈從items[0]-items[number-1]一個一個進行遍歷。如果相等,直接返回i,此時i就是陣列中item元素的位置;如果遍歷完整個陣列之後,都沒有發現與item相等的陣列元素,說明陣列中不存在item這個元素,於是返回-1.
4.向陣列中新增元素
bool Set::add_item(int item) { if(is_exist(item) >= 0 || this->number >= 100) { return false; } this->items[this->number] = item; this->number++; return true; }
首先判斷陣列中是否存在該元素,如果存在則不能再向集合中新增元素,直接返回false,如果不存在,則向陣列中的number所指向的那個位置新增該元素,然後number作為陣列元素個數的指示器+1,這樣就完成了新增元素。
5.保護陣列元素不被修改
寫到這裡,我們發現,陣列元素個數指示器this->number
,對於該問題的幾個演算法都起到了核心的作用,首先,我們依賴於陣列元素個數指示器遍歷陣列,如果number值遭到修改,會導致無法遍歷陣列。舉個例子來說,當我們呼叫下列語句以後:
Set set1; set1.add_item(1); set1.add_item(2); set1.add_item(3);
集合set1中的陣列items
變為[1,2,3]
,陣列元素個數指示器number=3
,此時,如果我們還想向集合set1
中新增元素20
,我們需要利用number=3
這個指示器,讓set1.items[number]
=20,並且讓number+1
以指向下一個位置,即number=4
。但是如果使用者手動修改number
值,比如set1.number=50
;此時,我們的number
就不再能指示陣列元素的正確位置,從而導致以上所有演算法所依賴的number
失效,因此,我們需要對陣列本身,以及陣列元素個數指示器number
進行私有化,以避免使用者隨意篡改。於是:
class Set { public: //建構函式和解構函式 Set() { this->number = 0; memset(this->items,0,sizeof(items)); } //初始化方法 int init(int items[], int num); //新增元素 bool add_item(int item); //刪除元素 int remove_item(int item); //求集合的並集 Set operator+ (Set set2); //求集合的交集 Set operator* (Set set2); //顯示集合元素 int display(); //判斷集合當中是否存在item,返回元素在集合中的位置,不存在返回-1 int is_exist(int item); private: int items[100]; //定義一個陣列作為容器存放100個集合元素 int number; //定義數字i表示集合中元素的個數 };
6. 從集合中移除元素
bool Set::remove_item(int item) { int pos = is_exist(item); if(pos == -1) return false; for(int i=pos; i< this->number-1; i++) { this->items[i] = this->items[i+1]; } this->number--; return true; }
首先檢查要移除的元素在結合中是否存在,如果不存在,則直接返回false
;其次,定位到集合中元素的位置,然後從這個位置開始將集合中剩餘的元素逐個前移,最後集合元素指示器-1,並返回true
.
7. 求兩個集合的交集
Set Set::operator* (Set set2) { Set result; for(int i=0; i< this->number; i++) { if(set2.is_exist(this->items[i]) >= 0) { result.items[result.number] = this->items[i]; result.number++; } } return result; }
演算法很簡單,遍歷集合A中的元素,對於A中的每一個元素判斷在集合B中是否存在,如果存在就加入到集合C當中,最後返回集合C
8. 求兩個集合的並集
Set Set::operator+ (Set set2) { Set result; for(int i=0; i<this->number; i++) { result.items[result.number] = this->items[i]; result.number++; } for(int j=0; j<set2.number; j++) { if(result.is_exist(set2.items[j]) == -1) { result.items[result.number] = set2.items[j]; result.number++; } } return result; }
首先遍歷集合A,將集合A中的元素全部加到集合C當中,然後遍歷集合B,對於B中的每一個元素,首先判斷是否在A中存在,如果不存在則將其加入到集合C中,最終返回集合C
相關文章
- 實現一個簡單的輪詢演算法演算法
- 實現一個簡單的DOM diff演算法演算法
- 如何實現一個簡單的以太坊?
- Bert文字分類實踐(一):實現一個簡單的分類模型文字分類模型
- 如何實現一個簡單易用的 RocketMQ SDKMQ
- 論如何用Vue實現一個彈窗-一個簡單的元件實現Vue元件
- 實現一個簡單的TomcatTomcat
- 使用WebSocket實現一個簡單的頁面聊天Web
- 使用JS實現一個簡單的選項卡效果JS
- 如何實現一個簡單的釋出訂閱模式模式
- 實現一個簡單的 RESTful APIRESTAPI
- 實現一個簡單的MVVM(Compile)MVVMCompile
- 簡單的實現一個原型鏈原型
- php實現一個簡單的socketPHP
- 從零實現一個RPC框架系列文章(二):11個類實現簡單RPCRPC框架
- 實現一個簡單的 jQuery 的 APIjQueryAPI
- 使用 Hooks 實現一個簡單的狀態管理器Hook
- 使用ABAP實現一個最簡單的區塊鏈原型區塊鏈原型
- 使用Netty和動態代理實現一個簡單的RPCNettyRPC
- 帶你實現一個簡單的MYSQL資料庫生成實體類工具MySql資料庫
- 動手實現一個簡單的promisePromise
- 用 go 實現一個簡單的 mvcGoMVC
- 實現一個簡單的虛擬DOM
- JavaScript之實現一個簡單的VueJavaScriptVue
- 使用Mongoose類庫實現簡單的增刪改查Go
- React 實現一個簡單實用的 Form 元件ReactORM元件
- 使用D3.js+Vue實現一個簡單的柱形圖JSVue
- 如何自己實現一個簡單的webpack構建工具 【精讀】Web
- 如何用Java Socket實現一個簡單的Redis客戶端JavaRedis客戶端
- 寫一個簡單的 Linux Shell (C++)LinuxC++
- C++寫一個簡單的JSON解析C++JSON
- 自己動手實現一個簡單的 IOC
- 實現一個簡單的 JavaScript 編譯器JavaScript編譯
- 手摸手教你實現一個簡單的PromisePromise
- Promise 原始碼:實現一個簡單的 PromisePromise原始碼
- 實現一個簡單的 std::unique_ptr
- 自己用 Netty 實現一個簡單的 RPCNettyRPC
- Java實現一個簡單的計算器Java
- 用canvas實現一個簡單的畫板Canvas