تعریف 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 آورده شده است.
برای راحتی یک دسترسی سریع به پیادهسازی ها با زبان های مختلف رو در زیر قرار دادیم.
پیادهسازی set با جاوا
میخوایم یک 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();
}
}
پیادهسازی set با کاتلین
در پایین میخوایم یک set رو به صورت جنریک در کاتلین پیاده کنیم.
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 با جاوااسکریپت
زبان جاوااسکریپت یک زبان type-free است یعنی نوع متغیر هنگام مقداردهیش مشخص میشه، در زیر میخوایم یک set رو با جاوااسکریپت پیاده کنیم.
class MyHashSet {
constructor() {
this.map = new MyHashMap();
}
add(e) {
if (this.map.containsKey(e)) return false;
this.map.put(e, null);
return true;
}
contains(e) {
return this.map.containsKey(e);
}
remove(e) {
if (!this.contains(e)) return false;
this.map.remove(e);
return true;
}
getSize() {
return this.map.getSize();
}
isEmpty() {
return this.map.isEmpty();
}
toArray() {
const size = this.map.getSize();
const elements = new Array(size);
const entries = this.map.toArray();
for (let i = 0; i < entries.length; i++) {
elements[i] = entries[i].getKey();
}
return elements;
}
toString() {
let sb = "[";
const array = this.toArray();
for (let i = 0; i < array.length; i++) {
sb += array[i];
if (i < array.length - 1) {
sb += ", ";
}
}
sb += "]";
return sb;
}
}
پیادهسازی set با پایتون
زبان پایتون یک زبان type-free است یعنی نوع متغیر هنگام مقداردهی مشخص میشه، در پایین میخوایم یک set رو در پایتون پیاده کنیم.
class MyHashSet:
def __init__(self):
self.map = MyHashMap()
def add(self, e):
if self.map.contains_key(e):
return False
self.map.put(e, None)
return True
def contains(self, e):
return self.map.contains_key(e)
def remove(self, e):
if not self.contains(e):
return False
self.map.remove(e)
return True
def get_size(self):
return self.map._size
def is_empty(self):
return self.map.is_empty()
def to_array(self):
size = self.map._size
elements = [None] * size
entries = self.map.to_array()
for i in range(len(entries)):
elements[i] = entries[i].get_key()
return elements
def __str__(self):
sb = "["
array = self.toArray()
for i in range(len(array)):
sb += str(array[i])
if i < len(array) - 1:
sb += ", "
sb += "]"
return sb
استفاده از 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)
let 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");
console.log(cities.toString());
cities = 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")
print(cities)
خلاصه
- از set در برنامه نویسی برای نگهداری عناصر غیر تکراری استفاده می کنیم.
- اگه بخوایم set رو از طریق هش کد (hashcode) پیاده کنیم بهش HashSet میگیم.
- میتونیم set رو مستقیم با هش کد یا از طریق رابطه ی aggregation با HashMap پیاده کنیم.
- پیچیدگی زمان برای اضافه، حذف و جستجوی عنصر در set برابر با O(1) است.
بازخورد و دیدگاه ها
اولین نفری باشید که در این صفحه نظر میدهید