تعریف set
در برنامه نویسی set نوعی پیاده سازی در ساختار داده است و set عناصر تکراری رو نگهداری نمیکنه
عنصر ها رو طبق ترتیبی که اضافه شدن نگهداری نمیکنه و بر خلاف لیست که با افزودن یک عنصر، عنصر بعد به طور خودکار تو خونه ی شماره ی بعدی آرایه قرار میگیره، در set با افزودن عنصر جدید، یک index تصادفی براش ایجاد میشه و به صورت تصادفی در خونه های موجود قرار می گیره.
در واقع set مشابه مجموعه ها در ریاضیاته یعنی یک مجموعه از عناصر که داخلش عنصر تکراری وجود نداشته باشه.
به set هایی که با هش کد (hashcode) پیاده می کنیم، HashSet میگیم، میتونیم HashSet رو مستقیم با هش کد یا از طریق یک رابطه ی aggregation با HashMap پیاده کنیم.
در این مطلب به پیاده سازی set از طریق رابطه ی aggregation با HashMap می پردازیم.
افزودن عنصر به set
برای اضافه کردن یک عنصر به set از تابعی به اسم add یا insert استفاده می کنیم؛ پیچیدگی زمان برای اضافه کردن یک عنصر به set برابر با O(1) است.
function add(E e): boolean{
if !map.contains(e)
return false
map.put(e, null)
size++
return true
}
بررسی وجود عنصر در set
برای بررسی یک عنصر در set از تابعی به نام contains استفاده می کنیم؛ در set پیچیدگی زمان برای جستجو O(1) است.
function contains(e: E): boolean{
return map.containsKey(e)
}
حذف عنصر از set
برای حذف یک عنصر در set از تابعی به نام remove یا delete استفاده می کنیم؛ پیچیدگی زمان در set برای حذف یک عنصر O(1) است.
function remove(e: E): boolean{
if !contains(e)
return false
map.remove(e)
return true
}
تبدیل set به آرایه برای جستجوی خطی بین عناصر
میتونیم با استفاده از تابعی به نام toArray عناصر رو به صورت آرایه برگردونیم تا بتونیم به جستجوی خطی بین عناصر بپردازیم، پیچیدگی زمان برای این کار O(n) است.
function toArray(): Object[] {
size := map.getSize()
elements := new Object[size]
entries := map.toArray()
for 0<= i < entries.length
elements[i] = entries[i]
return elements
}
پیاده سازی set در زبان های برنامه نویسی
میخوایم یک HashSet رو با رابطه ی aggregation با HashMap در زبان های برنامه نویسی (جاوا و کاتلین) پیاده کنیم.
در زیر نمودار uml پیاده سازی set آورده شده است.
public class MyHashSet<E> {
private final MyHashMap<E, Object> map = new MyHashMap<>();
public boolean add(E e){
if (map.containsKey(e)) return false;
map.put(e, null);
return true;
}
public boolean contains(E e){
return map.containsKey(e);
}
public boolean remove(E e){
if (!contains(e)) return false;
map.remove(e);
return true;
}
public int getSize() {
return map.getSize();
}
public boolean isEmpty(){
return map.isEmpty();
}
public Object[] toArray(){
int size = map.getSize();
Object[] elements = new Object[size];
MyHashMap.Entry<E, Object>[] entries = map.toArray();
for (int i=0; i<entries.length; i++){
elements[i] = entries[i].getKey();
}
return elements;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
Object[] array = toArray();
for (int i=0; i<array.length; i++){
sb.append(array[i]);
if (i < array.length - 1){
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
}
class MyHashSet<E> {
private val map: MyHashMap<E?, Any?> = MyHashMap()
val size: Int
get() = map.size
val isEmpty: Boolean
get() = map.isEmpty
fun add(e: E?): Boolean {
if (map.containsKey(e)) return false
map.put(e, null)
return true
}
fun contains(e: E?): Boolean {
return map.containsKey(e)
}
fun remove(e: E?): Boolean {
if (!contains(e)) return false
map.remove(e)
return true
}
fun toArray(): Array<Any?> {
val size: Int = map.size
val elements = arrayOfNulls<Any>(size)
val entries: Array<MyHashMap.Entry<E?, Any?>?> = map.toArray()
for (i in entries.indices) {
elements[i] = entries[i]?.key
}
return elements
}
override fun toString(): String {
val sb = StringBuilder("[")
val array = toArray()
for (i in array.indices) {
sb.append(array[i])
if (i < array.size - 1) {
sb.append(", ")
}
}
sb.append("]")
return sb.toString()
}
}
استفاده از set در زبان های برنامه نویسی
در این قسمت میخوایم یک نمونه از set که پیاده کردیم ایجاد کنیم و اسم چند شهر رو بهش اضافه کنیم و (اسم یک شهر رو دوبار بنویسیم) و سپس دو شهر رو حذف کنیم و در نهایت شهر های داخل set رو نمایش بدیم.
MyHashSet<String> cities = new MyHashSet<>();
cities.add("Tehran");
cities.add("Arak");
cities.add("Qom");
cities.add("Hamadan");
cities.add("Mashhad");
cities.add("Tehran");
cities.remove("Hamadan");
cities.remove("Arak");
System.out.println(cities);
val cities: MyHashSet<String> = MyHashSet()
cities.add("Tehran")
cities.add("Arak")
cities.add("Qom")
cities.add("Hamadan")
cities.add("Mashhad")
cities.add("Tehran")
cities.remove("Hamadan")
cities.remove("Arak")
println(cities)
خلاصه
- از set در برنامه نویسی برای نگهداری عناصر غیر تکراری استفاده می کنیم.
- اگه بخوایم set رو از طریق هش کد (hashcode) پیاده کنیم بهش HashSet میگیم.
- میتونیم set رو مستقیم با هش کد یا از طریق رابطه ی aggregation با HashMap پیاده کنیم.
- پیچیدگی زمان برای اضافه، حذف و جستجوی عنصر در set برابر با O(1) است.