Ctrl K
ComunidadGuías…

std/set.zc

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot

import "./option.zc"
import "./hash.zc"

import "./mem.zc"

struct Set<T> {
    data: T*;
    occupied: bool*;
    deleted: bool*;
    len: usize;
    cap: usize;
}

impl Set<T> {
    /// Creates a new, empty Set.
    fn new() -> Set<T> {
        return Set<T> { data: 0, occupied: 0, deleted: 0, len: 0, cap: 0 };
    }

    fn _resize(self, new_cap: usize) {
        let old_data = self.data;
        let old_occupied = self.occupied;
        let old_deleted = self.deleted;
        let old_cap = self.cap;

        self.cap = new_cap;
        self.data = alloc_n<T>(new_cap);
        self.occupied = alloc_n<bool>(new_cap);
        self.deleted = alloc_n<bool>(new_cap);
        memset(self.data, 0, new_cap * sizeof(T));
        memset(self.occupied, 0, new_cap * sizeof(bool));
        memset(self.deleted, 0, new_cap * sizeof(bool));
        self.len = 0;

        for (let i: usize = 0; i < old_cap; i = i + 1) {
            if (old_occupied[i] && !old_deleted[i]) {
                self.add(old_data[i]);
            }
        }

        if (old_data != NULL) { dealloc<T>(old_data); }
        if (old_occupied != NULL) { dealloc<bool>(old_occupied); }
        if (old_deleted != NULL) { dealloc<bool>(old_deleted); }
    }

    /// Inserts a value; returns whether it was new.
    fn add(self, val: T) -> bool {
        if (self.contains(val)) {
            return false;
        }

        if (self.len >= self.cap * 0.75) {
            let new_cap = self.cap * 2;
            if (new_cap < 8) new_cap = 8;
            self._resize(new_cap);
        }

        let hash = hash_compute(&val, sizeof(T));
        let idx = hash % self.cap;

        while (self.occupied[idx] && !self.deleted[idx]) {
            idx = (idx + 1) % self.cap;
        }

        self.data[idx] = val;
        self.occupied[idx] = true;
        self.deleted[idx] = false;
        self.len = self.len + 1;
        return true;
    }

    /// Returns whether the value is present.
    fn contains(self, val: T) -> bool {
        if (self.cap == 0) {
            return false;
        }

        let hash = hash_compute(&val, sizeof(T));
        let idx = hash % self.cap;
        let start_idx = idx;

        while (self.occupied[idx]) {
            if (!self.deleted[idx] && self.data[idx] == val) {
                return true;
            }

            idx = (idx + 1) % self.cap;
            if (idx == start_idx) {
                return false;
            }
        }
        return false;
    }

    /// Removes a value; returns whether it was present.
    fn remove(self, val: T) -> bool {
        if (self.cap == 0) return false;

        let hash = hash_compute(&val, sizeof(T));
        let idx = hash % self.cap;
        let start_idx = idx;

        while (self.occupied[idx]) {
            if (!self.deleted[idx] && self.data[idx] == val) {
                self.deleted[idx] = true;
                self.len = self.len - 1;
                return true;
            }

            idx = (idx + 1) % self.cap;
            if (idx == start_idx) return false;
        }
        return false;
    }

    /// Returns the number of items.
    fn length(self) -> usize {
        return self.len;
    }

    /// Returns whether the set is empty.
    fn is_empty(self) -> bool {
        return self.len == 0;
    }

    /// Frees the backing storage.
    fn free(self) {
        if (self.data) {
            dealloc<T>(self.data);
            dealloc<bool>(self.occupied);
            dealloc<bool>(self.deleted);
        }
        self.data = 0;
        self.occupied = 0;
        self.deleted = 0;
        self.len = 0;
        self.cap = 0;
    }

    fn capacity(self) -> usize {
        return self.cap;
    }

    fn is_slot_occupied(self, idx: usize) -> bool {
        if (idx >= self.cap) return false;
        return self.occupied[idx] && !self.deleted[idx];
    }

    fn val_at(self, idx: usize) -> Option<T> {
        if (idx >= self.cap || !self.occupied[idx] || self.deleted[idx]) {
            return Option<T>::None();
        }
        return Option<T>::Some(self.data[idx]);
    }
    /// Removes all items.
    fn clear(self) {
        for (let i: usize = 0; i < self.cap; i = i + 1) {
            self.occupied[i] = false;
            self.deleted[i] = false;
        }
        self.len = 0;
    }
}

impl Drop for Set<T> {
    fn drop(self) {
        self.free();
    }
}