XorLinkedList

    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    last year
    Downloads
    38

    No dependencies

    #XorLinkedList

    A high-performance XOR linked list implemented in MoonBit, which is a memory-efficient doubly linked list data structure that saves memory space by storing the XOR value of adjacent node addresses. XorLinkedList maintains all the functionality of a doubly linked list while reducing pointer usage by 50%, making it suitable for linked list operations in memory-constrained environments.

    #🚀 Core Features

    • 🔗 Memory Efficient – Uses a single pointer field to implement bidirectional links, saving nearly 50% memory • ⚡ Bidirectional Traversal – Supports efficient traversal from head to tail and tail to head • 🔧 Node ID Reuse – Intelligently reuses released node IDs to avoid memory waste • 📊 Rich API – Supports comprehensive linked list operations, including search, sort, transformation, and more • 🧩 Generic Types – Supports storage and operations of any data type • 🔄 Advanced Collection Operations – Provides mapping, filtering, folding, and other functional programming operations • 📈 Dynamic Expansion – Automatically expands internal storage as needed • 🔍 Powerful Queries – Supports various query methods based on index and value

    #📥 Installation

    moon add SupremeHuaji/XorLinkedList

    #🚀 Usage Guide

    #🔨 Creating a List

    Multiple ways to create and initialize a list.

    // Create an empty list
    let list = new()

    // Add elements
    list.push_front(1) // Add to the front
    list.push_back(3) // Add to the back
    list.push_front(0) // Result: [0, 1, 3]

    // Check basic information
    println("List length: \{list.len()}") // Output: 3
    println("Is list empty: \{list.is_empty()}") // Output: false

    #➕ Adding and Removing Elements

    Use push_front, push_back, pop_front, and pop_back methods to manipulate the list.

    let list = new()

    // Add elements
    list.push_back(10)
    list.push_back(20)
    list.push_front(5) // [5, 10, 20]

    // Remove elements
    let first = list.pop_front() // first = Some(5), list = [10, 20]
    println("Removed first element: \{first}")

    let last = list.pop_back() // last = Some(20), list = [10]
    println("Removed last element: \{last}")

    // Clear the list
    list.clear()
    println("Length after clearing: \{list.len()}") // Output: 0

    #🔍 Accessing Elements

    Multiple ways to access list elements.

    let list = new()

    // Add test data
    list.push_back(10)
    list.push_back(20)
    list.push_back(30)
    list.push_back(40)

    // Access by index
    let element = list.get(2)
    println("Element at index 2: \{element}") // Output: Some(30)

    // Get first and last elements
    let first = list.head()
    let last = list.last()
    println("First element: \{first}, Last element: \{last}") // Output: Some(10), Some(40)

    // Find elements
    let index = list.index_of(30)
    println("Index of element 30: \{index}") // Output: Some(2)

    // Check if an element exists
    if list.contains(20) {
    println("List contains element 20")
    }

    #🎯 Traversal and Transformation

    Forward and reverse traversal of the list, as well as transformation operations.

    let list = new()

    // Add test data
    list.push_back(1)
    list.push_back(2)
    list.push_back(3)

    // Forward traversal
    println("Forward traversal:")
    list.each(fn(val) {
    println(" \{val}")
    })

    // Reverse traversal
    println("Reverse traversal:")
    list.each_reverse(fn(val) {
    println(" \{val}")
    })

    // Convert to array
    let array = list.to_array()
    println("List converted to array: \{array}") // Output: [1, 2, 3]

    #🔄 Functional Operations

    Use functional programming paradigms to process the list.

    let list = new()

    // Add test data
    list.push_back(1)
    list.push_back(2)
    list.push_back(3)
    list.push_back(4)
    list.push_back(5)

    // Map operation: double each element
    let doubled = list.map(fn(x) { x * 2 })
    println("After doubling: \{doubled.to_array()}") // Output: [2, 4, 6, 8, 10]

    // Filter operation: keep only even numbers
    let evens = list.filter(fn(x) { x % 2 == 0 })
    println("Even elements: \{evens.to_array()}") // Output: [2, 4]

    // Fold operation: calculate sum
    let sum = list.fold(0, fn(acc, x) { acc + x })
    println("Sum of elements: \{sum}") // Output: 15

    // Take first N elements
    let first_three = list.take(3)
    println("First three elements: \{first_three.to_array()}") // Output: [1, 2, 3]

    #🛠️ Structure Modification

    Advanced operations that modify the list structure.

    let list = new()

    // Add unsorted data
    list.push_back(3)
    list.push_back(1)
    list.push_back(4)
    list.push_back(2)

    // Sort the list
    list.sort()
    println("After sorting: \{list.to_array()}") // Output: [1, 2, 3, 4]

    // Reverse the list
    list.reverse()
    println("After reversing: \{list.to_array()}") // Output: [4, 3, 2, 1]

    // Insert separator values between elements
    let separated = list.intersperse(0)
    println("After inserting separators: \{separated.to_array()}") // Output: [4, 0, 3, 0, 2, 0, 1]

    // Remove an element at a specific position
    let removed = list.remove_at(1)
    println("Removed element at index 1: \{removed}") // Output: Some(3)
    println("After removal: \{list.to_array()}") // Output: [4, 2, 1]

    #🔗 Merging Operations

    Merge and connect multiple lists.

    let list1 = new()
    list1.push_back(1)
    list1.push_back(2)

    let list2 = new()
    list2.push_back("a")
    list2.push_back("b")

    // Zip two lists into a tuple list
    let zipped = list1.zip(list2)
    println("Zip result:")
    zipped.each(fn(pair) {
    println(" \{pair.0} - \{pair.1}")
    })
    // Output:
    // 1 - a
    // 2 - b

    #📊 Performance Characteristics

    OperationTime ComplexitySpace ComplexityDescription
    new()O(1)O(1)Create an empty list
    push_front()O(1)O(1)Add an element to the front of the list
    push_back()O(1)O(1)Add an element to the back of the list
    pop_front()O(1)O(1)Remove an element from the front of the list
    pop_back()O(1)O(1)Remove an element from the back of the list
    get(index)O(n)O(1)Access an element at a specific position
    each()O(n)O(1)Traverse all elements
    contains()O(n)O(1)Check if an element exists
    map()O(n)O(n)Map to a new list
    sort()O(n log n)O(n)Sort the list

    Where:
    • n = Number of elements in the list

    #🏗️ Implementation Details

    XorLinkedList is based on XOR linked list technology, using XOR operations to combine predecessor and successor pointers:

    #📦 Core Data Structures

    1. Node Structure (Node)
      • Content: Stores the actual value and a link field
      • Link Field: XOR of predecessor node ID and successor node ID
      • Advantage: Implements bidirectional linking with a single pointer

    2. List Structure (T)
      • Head and Tail Pointers: Track the first and last nodes of the list
      • Node Array: Stores all nodes
      • Free ID List: Tracks reusable node positions
      • Size Counter: Current number of list elements

    #🔄 XOR Linked List Working Principle

    // XOR Linked List Basic Principle
    // Assuming nodes A, B, C are linked in sequence:

    // Regular Doubly Linked List:
    // A.prev = null, A.next = &B
    // B.prev = &A, B.next = &C
    // C.prev = &B, C.next = null
    // Total of 6 pointer fields required

    // XOR Linked List:
    // A.link = null XOR &B = &B
    // B.link = &A XOR &C
    // C.link = &B XOR null = &B
    // Total of 3 pointer fields required, saving 50% memory

    // Traversal Method:
    // Starting from A, knowing prev=null:
    // next = prev XOR A.link = null XOR &B = &B
    // Move to B, and remember prev=&A
    // Continue from B, knowing prev=&A:
    // next = prev XOR B.link = &A XOR (&A XOR &C) = &C
    // Move to C, and remember prev=&B
    // And so on...

    #📈 Node ID Reuse Mechanism

    For efficient memory usage, XorLinkedList uses a node ID reuse mechanism:

    // When a node is deleted:
    1. Disconnect the node from the list
    2. Add the node ID to the free ID list
    3. Set the corresponding position in the node array to None

    // When a new node is created:
    1. Preferentially get an ID from the free ID list
    2. If the free list is empty, add a new node at the end of the node array

    #🆚 XorLinkedList vs Traditional Linked Lists

    FeatureRegular Doubly Linked ListXorLinkedList
    Memory UsageTwo pointers per nodeOne pointer per node
    Bidirectional TraversalSupportedSupported
    Random AccessO(n)O(n)
    Implementation ComplexitySimpleMedium
    Pointer OperationsDirectRequires remembering the previous node
    Memory SavingsBaselineUp to 50%
    Suitable ScenariosGeneralMemory-constrained environments

    #🤝 Contributing

    Contributions are welcome! Please follow these steps:

    1. Fork this repository
    2. Create a feature branch (git checkout -b feature/AmazingFeature)
    3. Commit your changes (git commit -m 'Add some AmazingFeature')
    4. Push to the branch (git push origin feature/AmazingFeature)
    5. Open a Pull Request

    #📜 License

    This project is licensed under the Apache-2.0 License. See the LICENSE file for details.

    Node

    pub(all) struct Node[A] {
    value : A
    link : Int
    }
    XOR链表节点结构
    impl Eq for Node[A]
    pub(all) struct T[A] {
    head : Int
    tail : Int
    nodes : Array[Node[A]?]
    free_ids : Array[Int]
    size : Int
    }

    impl Eq for T[A]

    T::allocate_node_id

    fn[A] T::allocate_node_id(self : T[A]) -> Int
    分配新节点ID

    T::clear

    fn[A] T::clear(self : T[A]) -> Unit
    清空链表

    T::contains

    fn[A : Eq] T::contains(self : T[A], value : A) -> Bool
    检查链表是否包含指定元素

    T::drop

    fn[A] T::drop(self : T[A], n : Int) -> T[A]
    丢弃前n个元素,保留剩余元素

    T::each

    fn[A] T::each(self : T[A], f : (A) -> Unit) -> Unit
    遍历链表(从头到尾)

    T::each_reverse

    fn[A] T::each_reverse(self : T[A], f : (A) -> Unit) -> Unit
    反向遍历链表(从尾到头)

    T::filter

    fn[A] T::filter(self : T[A], predicate : (A) -> Bool) -> T[A]
    筛选符合条件的元素并创建新链表

    T::find

    fn[A] T::find(self : T[A], predicate : (A) -> Bool) -> A?
    查找符合条件的第一个元素

    T::find_index

    fn[A] T::find_index(self : T[A], predicate : (A) -> Bool) -> Int?
    查找符合条件的第一个元素的索引

    T::fold

    fn[A, B] T::fold(self : T[A], initial : B, f : (B, A) -> B) -> B
    聚合链表元素

    T::free_node_id

    fn[A] T::free_node_id(self : T[A], id : Int) -> Unit
    释放节点ID(添加到空闲列表)

    T::get

    fn[A] T::get(self : T[A], index : Int) -> A?
    获取指定位置的元素(从0开始计数)

    T::head

    fn[A] T::head(self : T[A]) -> A?
    获取链表的第一个元素

    T::index_of

    fn[A : Eq] T::index_of(self : T[A], value : A) -> Int?
    查找特定元素的索引

    T::intersperse

    fn[A] T::intersperse(self : T[A], separator : A) -> T[A]
    在元素之间插入分隔值

    T::is_empty

    fn[A] T::is_empty(self : T[A]) -> Bool
    链表是否为空

    T::is_sorted

    fn[A : Compare + Eq] T::is_sorted(self : T[A]) -> Bool
    检查链表元素是否按升序排列

    T::last

    fn[A] T::last(self : T[A]) -> A?
    获取链表的最后一个元素

    T::len

    fn[A] T::len(self : T[A]) -> Int
    获取链表大小

    T::map

    fn[A, B] T::map(self : T[A], f : (A) -> B) -> T[B]
    将函数应用到所有元素并创建新链表

    T::pop_back

    fn[A] T::pop_back(self : T[A]) -> A?
    从链表后端移除元素

    T::pop_front

    fn[A] T::pop_front(self : T[A]) -> A?
    从链表前端移除元素

    T::push_back

    fn[A] T::push_back(self : T[A], value : A) -> Unit
    在链表后端添加元素

    T::push_front

    fn[A] T::push_front(self : T[A], value : A) -> Unit
    在链表前端添加元素

    T::remove

    fn[A : Eq] T::remove(self : T[A], value : A) -> Bool
    移除第一个匹配的元素

    T::remove_at

    fn[A] T::remove_at(self : T[A], index : Int) -> A?
    移除指定位置的元素

    T::reverse

    fn[A] T::reverse(self : T[A]) -> Unit
    反转链表

    T::sort

    fn[A : Compare + Eq] T::sort(self : T[A]) -> Unit
    排序链表(使用归并排序)

    T::take

    fn[A] T::take(self : T[A], n : Int) -> T[A]
    获取前n个元素组成的新链表

    T::to_array

    fn[A] T::to_array(self : T[A]) -> Array[A]
    转换为数组

    T::zip

    fn[A, B] T::zip(self : T[A], other : T[B]) -> T[(A, B)]
    将两个链表合并为一个包含元组的链表

    new

    fn[A] new() -> T[A]
    创建一个新的XOR链表