{"id":20782734,"url":"https://github.com/khaledhosseini/polygolt-dsa","last_synced_at":"2026-04-12T13:07:28.848Z","repository":{"id":191282544,"uuid":"683811835","full_name":"KhaledHosseini/polygolt-dsa","owner":"KhaledHosseini","description":"Data structures and algorithms for polyglot programmers.","archived":false,"fork":false,"pushed_at":"2024-10-11T13:36:58.000Z","size":42004,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-18T09:20:58.423Z","etag":null,"topics":["algorithms","cpp","csharp","datastructures","dsa","java","javascript","python","swift"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/KhaledHosseini.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-27T19:17:22.000Z","updated_at":"2024-11-11T18:06:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"30e0d75a-79e1-4981-a588-24f3ef6fd07e","html_url":"https://github.com/KhaledHosseini/polygolt-dsa","commit_stats":null,"previous_names":["khaledhosseini/polygolt-algorithm"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KhaledHosseini%2Fpolygolt-dsa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KhaledHosseini%2Fpolygolt-dsa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KhaledHosseini%2Fpolygolt-dsa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KhaledHosseini%2Fpolygolt-dsa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KhaledHosseini","download_url":"https://codeload.github.com/KhaledHosseini/polygolt-dsa/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243125638,"owners_count":20240276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","cpp","csharp","datastructures","dsa","java","javascript","python","swift"],"created_at":"2024-11-17T14:14:23.716Z","updated_at":"2025-12-24T13:37:59.860Z","avatar_url":"https://github.com/KhaledHosseini.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"![Header](files/header.png)\n\nThe link to the article at [dev.to](https://dev.to/khaledhosseini/data-structures-and-algorithms-for-multi-language-programmers-c-swift-python-java-c-javascript-alp)\n\nIn programming languages, predefined data structures are widely used, but their names and how they work can differ from one language to another. Despite these differences, the core ideas behind these structures stay the same. In this article, we will take a deep dive into data structures, looking at how they are set up in various programming languages. To make understanding easier, we will include short animations to help you grasp these concepts. Although the title specifically mentions \"Multi-language programmers,\" it is evident that mono-language programmers can also derive significant benefits from this article.This article marks the beginning of a series, where we delve into a range of essential topics. The series will cover the following main subjects:\n- Linear data structures\n- Non-linear data structures\n- Algorithms\n\n---\n\n- [Memory](#memory)\n  - [Physical layer](#physical-layer)\n  - [Virtual layer](#virtual-layer)\n    - [Location](#location)\n    - [Arrangement](#arrangement)\n- [Algorithms](#algorithms)\n  - [Fundamental operations](#fundamental-operations)\n  - [Fundamental Algorithms](#fundamental-algorithms)\n    - [Sorting algorithms](#sorting-algorithms)\n    - [Searching algorithms](#searching-algorithms)\n  - [Algorithm design techniques](#algorithm-design-techniques)\n- [Data structures](#data-structures)\n  - [Contiguous Memory data structures](#contiguous-memory-data-structures)\n  - [Discontiguous Memory data structures](#discontiguous-memory-data-structures)\n  - [Combination of CM and DCM](#combination-of-cm-and-dcm)\n  - [Linear data structures](#linear-data-structures)\n    - [Array](#array)\n    - [DynamicArray](#dynamicarray)\n    - [RingBuffer](#ringbuffer)\n    - [LinkedList](#linkedlist)\n    - [FreeList](#freelist)\n    - [DoubleLinkedList](#doublelinkedlist)\n    - [CircularLinkedList](#circularlinkedlist)\n    - [CircularDoubleLinkedList](#circulardoublelinkedlist)\n    - [Stack](#stack)\n      - [Stack via DynamicArray](#stack-via-dynamicarray)\n      - [Stack via LinkedList](#stack-via-linkedlist)\n      - [Stack via deque](#stack-via-deque)\n    - [Queue](#queue)\n      - [Queue via DoubleLinkedList](#queue-via-doublelinkedlist)\n      - [Queue via RingBuffer](#queue-via-ringbuffer)\n      - [Queue via Double Stack](#queue-via-double-stack)\n      - [Deque as Queue](#deque-as-queue)\n    - [Deque](#deque)\n      - [Deque via DoubleLinkedList](#deque-via-doublelinkedlist)\n      - [Deque via Array](#deque-via-array)\n    - [PriorityQueue](#priorityqueue)\n      - [PriorityQueue via DynamicArray](#priorityqueue-via-dynamicarray)\n      - [PriorityQueue via LinkedList](#priorityqueue-via-linkedlist)\n      - [PriorityQueue via Deque](#priorityqueue-via-deque)\n      - [PriorityQueue via BinaryHeap](#priorityqueue-via-binaryheap)\n    - [Associative collections](#associative-collections)\n      - [UnorderedMap or HashTable](#unorderedmap-or-hashtable)\n      - [OrderedMap via HashTable and LinkedList](#orderedmap-via-hashtable-and-linkedlist)\n      - [OrderedMap via HashTable and DynamicArray](#orderedmap-via-hashtable-and-dynamicarray)\n      - [SortedMap via Self Balancing Tree](#sortedmap-via-self-balancing-tree)\n    - [Set](#set)\n      - [UnorderedSet](#unorderedset)\n      - [OrderedSet via HashTable and LinkedList](#orderedset-via-hashtable-and-linkedlist)\n      - [SortedSet via Self Balancing Tree](#sortedset-via-self-balancing-tree)\n    - [SkipList](#skiplist)\n    - [standard library data structures](#standard-library-data-structures)\n      - [C++](#c)\n      - [Swift](#swift)\n      - [CSharp](#csharp)\n      - [Python](#python)\n      - [Java](#java)\n  - [Non-Linear structures](#non-linear-structures)\n    - [Tree](#tree)\n      - [General Tree](#general-tree)\n      - [k-ary Tree](#k-ary-tree)\n      - [BinaryTree](#binarytree)\n        - [BinarySearchTree](#binarysearchtree)\n        - [AVLTree](#avltree)\n        - [RedBlackTree](#redblacktree)\n        - [B Tree](#b-tree)\n        - [Splay Tree](#splay-tree)\n        - [KD Tree](#kd-tree)\n        - [HeapTree](#heaptree)\n        - [Cartesian Tree](#cartesian-tree)\n        - [Fibonacci Heap](#fibonacci-heap)\n        - [Segment Tree](#segment-tree)\n        - [Merkle Tree](#merkle-tree)\n      - [Trie](#trie)\n    - [Graph](#graph)\n- [Augmented data structures](#augmented-data-structures)\n  - [Algorithms](#algorithms-1)\n\n\nSuppose you have a collection of data blocks, denoted as |A|, |B|, |C|, |D|, |E|, and so on. Your objective is to solve a problem by employing an algorithm that processes this data and produces a result. Irrespective of the specific problem or algorithm you opt for, there are certain steps that need to be followed:\n1. Allocate some space (memory) to your data.\n2. Arrange your data-blocks in the allocated space and create a logical relationship(Implicit or explicit) among them (Specify a `Data Structure`).\n3. Doing Some operations on the data-blocks(`Algorithm`): These operations may include:\n  - Read data-blocks\n  - Write data-blocks\n\nData structures and algorithms are closely intertwined concepts. Certain algorithms exhibit better efficiency when used with specific data structures, and conversely, certain data structures offer advantageous arrangements that enhance the efficiency of particular algorithms. To efficiently solve problems, it is crucial to design both efficient algorithms and appropriate data structures. Designing these efficient solutions necessitates a solid understanding of the fundamentals and analysis techniques involved.\n\n---\n\n## Memory\n### Physical layer\nThe physical layer of a computer system is responsible for the actual storage and retrieval of data in electronic or magnetic form. Memory in the physical layer is organized hierarchically, with different types and levels of memory. Types of Memory in the Physical Layer:\n- Registers\n- Cache Memory\n- Main Memory (Random Access Memory - RAM)\n- Secondary memories: (HDD,SSD,...)\u003cbr\u003e\nPhysical memory is invisible to programs in virtual memory systems and as a programmer you're not required to reason about it.\n\n### Virtual layer\nWhere and how memory is being allocated in virtual layer?\n\n#### Location\n\n- `Stack`: Fast allocation. Faster access.\n  1. Moving just an integer pointer allocates/de-allocates memory.\n- `Heap`: Slow Allocation. Slower access.\n  1. Search heap.\n  2. Sync heap for other threads.\n  3. Allocate memory.\n\n#### Arrangement\n\n- `Contiguous`: Bulk allocation in continuous memory block. (faster access).\n- `Discontiguous`: Dynamic allocation in separated memory blocks.(slower access).\n\n---\n\n## Algorithms\nAt the core of all algorithms are the fundamental operations that involve `accessing` and potentially `mutating` the data blocks, regardless of how we arrange our data-blocks in memory and what are the logical connections between them. At this level, all algorithms can be reduced to one or some of the following operations.\n\n### Fundamental operations\n\n- `read`\n  - accessDataBySequence() (Either forward or backward)\n  - getIndexingInformation(): `getStartIndex()`, `getEndIndex()`, `getNextIndex(forIndex)`, `getPreviousIndex(forIndex)`\n  - accessDataAtRandomIndex(:): For Random access, time complexity should be of order `O(1)`.\n  - accessDataAtFront()\n  - accessDataAtBack()\n- `write`\n  - insertDataAtRandomIndex(:)\n  - insertDataAtFront()\n  - insertDataAtBack()\n  - removeDataAtRandomIndex(:)\n  - removeDataAtFront()\n  - removeDataAtBack()\n  - updateDataAtRandomIndex(:)\n  - updateDataAtFront()\n  - updateDataAtBack()\n\nFor example, `Linear search` algorithm uses `accessDataBySequence` and compare each item  with a specified value to find the answer while `Binary search` algorithm needs `accessDataAtRandomIndex` operation.\u003cbr\u003e \nA note on `Random Access`: In the context of data structures, random access refers to the ability to instantly access a specific location. With [Array](#array), for instance, if you select a random index, the Array data structure can immediately provide you with the address of that index. However, if you attempt to access a random index in a [LinkedList](#linkedlist), the data structure cannot instantaneously provide the address. Instead, it must iterate from the beginning (starting from head) until it reaches the desired index. Consequently, LinkedLists are considered to have a time complexity of `O(n)` (Upper bound) for random access operation. Most algorithms require `O(1)` random access, and languages such as Java have introduced a marker interface(with no methods) called [RandomAccess](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/RandomAccess.java). This interface serves as a reminder that certain algorithms rely on random access. To ensure that these algorithms perform efficiently with your data structure, it is necessary to make it compatible with random access. The Swift equivalent is a marker protocol [RandomAccessCollection](https://github.com/apple/swift/blob/main/stdlib/public/core/RandomAccessCollection.swift).\n\n### Fundamental Algorithms\nFundamental operations form the building blocks upon which algorithms are constructed. Conversely, certain algorithms play fundamental rules for other algorithms. Take, for instance, the impact of input data order on the time efficiency of algorithms. Sorting the data beforehand can greatly simplify our lives, as it has a significant positive effect on the efficiency of numerous algorithms. Sorting can be accomplished through two methods. The first method involves utilizing a sorting algorithm to arrange an unsorted collection. The second method involves utilizing specific data structures, such as binary search trees, that facilitate the sorting of data through amortization.\n\n#### Sorting algorithms\nAll sort algorithms need `getIndexingInformation`, `accessDataAtRandomIndex(:)` operations. Also items must be comparable (unless for non-comparison algorithms).\n- In-place sorting algorithms: They need  `updateDataAtRandomIndex(:)` operation.\n  1. Bubble sort\n  2. Selection sor\n  3. Insertion sort\n  4. Heap sort\n  5. Quick sort\n- Not In-Place Sorting Algorithms:\n  1. Merge sort\n  2. Radix sort (non-comparison)\n  3. Bucket sort (non-comparison)\n\n#### Searching algorithms\n- Linear search: needs `accessDataBySequence()`\n- Binary search: needs `accessDataAtRandomIndex(:)` with `O(1)`\n\n### Algorithm design techniques\n- Divide and conquer\n- Recursion\n- Randomized algorithms: Input MUST be RANDOM.\n- Dynamic programming\n- Greedy algorithms\n- Parallel algorithms\n\nIn a next article, I will return to the algorithms. \n\n---\n\n## Data structures\nEach data structure has the following characteristics:\n- `Virtual layer Memory management` at the virtual layer.\n- `Logical connection` between data-blocks, either `implicit` or `explicit`.\n  - Implicit: In an [Array](#array)  data-blocks have no direct connection, but implicitly they are arranged in a specific order contiguously in memory.\n  - Explicit: In [LinkedList](#linkedlist) the blocks may not be stored contiguously in memory, but each node has the connection information to some other nodes.\n- `Rules` for applying basic operations.\n- Provides basic `read` and `write` operations with a space/time complexity. The space/time complexities for data structures for basic operations can easily be analyzed using the following concepts: [Contiguous Memory data structures](#contiguous-memory-data-structures) and [Discontiguous Memory data structures](#discontiguous-memory-data-structures)\n\n### Contiguous Memory data structures\n- Init with fixed size. size stays fixed.\n- Address of each block can be calculated via: `start + k * blocksize`. Random access time complexity is `O(1)`\n- Bulk memory allocation\n- Same size memory blocks (Same type: Homogeneous)\n- Base data Structure example: Array\n\n![Contiuous-Memory data structure](files/continuous_memory_ds.drawio.svg)\n\n### Discontiguous Memory data structures\n- This arrangement is a special kind of Graph (We can represent graphs using it).\n- Each block contains the address of a next block.\n- Time complexity for random access operation is `O(n)`\n- Dynamic memory allocation\n- Memory block sizes can be different (Different types: Heterogeneous).\n- Base data structure example: LinkedList\n\n![Discontinuous-Memory data structure](files/discontinuous_memory_ds.drawio.svg)\n\n### Combination of CM and DCM\n- A contiguous-memory array of pointers to contiguous-memory or discontiguous-memory collection of objects. \n- Time complexity for random access operations is `O(1)` (via array of pointers) but accessing objects in non-continuous memory have a little overhead.\n- Bulk memory allocation for address (pointer) array, dynamic memory allocation for objects.\n- Objects can have different memory sizes (different types).\n- Base data structure example: An array of referenced objects in most programming languages.\n\n![CM and DCM Combination](files/cm_dcm_combiniation.drawio.svg)\n\n\n### Linear data structures\nBy employing one or a combination of the aforementioned concepts, basic data structures can be implemented, serving as the foundation for more intricate data structures. Additionally, the space and time complexities, as well as memory costs, can be readily analyzed by leveraging the complexities and costs associated with these fundamental concepts.\n\n#### Array\nIn Programming languages, Arrays are built-in types. Array of pointers (or array of reference types) acts like [Combination of CM and DCM](#combination-of-cm-and-dcm). For primitive types (or value types like Int, enum, struct in C#,Swift,...) the behavior is like [Contiguous Memory data structures](#contiguous-memory-data-structures).\n- `Basic operations` time complexity: Same as [Contiguous Memory data structures](#contiguous-memory-data-structures)\n- `Good`: \n  - `accessAtRandomIndex`, `insertAtBack`, `removeAtBack` operations. \n  - Bulk memory allocation (fast).\n  - Contiguous memory. Fast access.\n  - If used with primitive types (Value types), no dynamic memory allocation cost.\n- `Not good`:\n  - `insertAtFront`, `insertAtMiddle`, `removeAtFront`, `removeAtMiddle` Operations. \n  - Fixed size.\n- Programming Languages implementations:\n  - Cpp: [Array](https://cplusplus.com/reference/array/array/) size is compile-time constant.\n  - Swift: Arrays in swift are dynamic.\n  - Python: Python [array](https://docs.python.org/3/library/array.html) size is compile-time constant.\n  - Java: [array](https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html) size is compile-time constant.\n  - C#: [Array](https://learn.microsoft.com/en-us/dotnet/api/system.array?view=net-7.0) size is compile-time constant.\n  - JavaScript: Arrays in Javascript are dynamic.\n\n![Array_gif](files/Array_ManimCE_v0.17.3.gif)\n\n#### DynamicArray\nSimilar to array, but can grow at runtime. DynamicArray of pointers (or DynamicArray of reference types) acts like [Combination of CM and DCM](#combination-of-cm-and-dcm). For primitive types (or value types like Int, enum, struct in C#,Swift,...) the behavior is like [Contiguous Memory data structures](#contiguous-memory-data-structures). Steps for resizing:\n  - allocate new array with new size\n  - copy the old array values to the new array\n  - delete the old array\n- `Basic operations` time complexity: Same as [Contiguous Memory data structures](#contiguous-memory-data-structures)\n- `Good`: \n  - `accessAtRandomIndex`, `insertAtBack`, `removeAtBack` operations. \n  - Bulk memory allocation (fast).\n  - If used with primitive types (Value types), no dynamic memory allocation cost.\n- `Not good`: \n  - `insertAtFront`, `insertAtMiddle`, `removeAtFront`, `removeAtMiddle` Operations. \n  - New memory allocations and copy cost when capacity is full. \n  - Has unused memory allocation based on growth strategy. For example in Swift programming language, each time an array capacity is full, it double the capacity of the array.\n- Programming Languages implementations:\n  - Cpp: [Vector](https://cplusplus.com/reference/vector/vector/).\n  - Swift: [contiguousarray](https://developer.apple.com/documentation/swift/contiguousarray) and [array](https://developer.apple.com/documentation/swift/array) are dynamic. When capacity is full, the size gets doubled.\n  - Python: [list](https://docs.python.org/3/library/stdtypes.html#lists) is a dynamic array of pointers to other objects. The behavior is always like [Combination of CM and DCM](#combination-of-cm-and-dcm). [UserList](https://docs.python.org/3/library/collections.html#collections.UserList) is a wrapper class that allows you to create your own list-like objects by inheriting from UserList and implementing certain methods. It provides a convenient way to create custom list-like classes without directly subclassing the built-in list class.\n  - Java: [ArrayList](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html) and [Vector](https://docs.oracle.com/javase/8/docs/api/java/util/Vector.html) are dynamic and the difference is that vector is thread-safe.\n  - C#: [ArrayList](https://learn.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=net-7.0) and [List](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-7.0) are dynamic arrays. The difference is that `ArrayList` is non-generic and can store elements of any while `List\u003cT\u003e` is a generic class that provides type-safe collections.\n  - JavaScript: When it comes to Javascript, things are a little bit different. [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) is dynamic and you can add multiple types to it. As Array is an Object and Objects in javascript are HashTables, you can access indices of array using string of indices too!  Depending on the type of the values, the behavior of Javascript array is different. \n    - In [V8 Engine](https://github.com/v8/v8) when Array only contains a single primitive type (like integer, float, ...) it’ll be backed by a C++ array of that type and the behavior is like [Contiguous Memory data structures](#contiguous-memory-data-structures).\n    - When Array contains more than one of primitive types, the array will be backed by a C++ array of the bigger one and the behavior is the same as above.\n    - If the array contains only objects, or a mixture of numbers and objects, it’ll backed by an array of pointers (primitive types will be boxed inside objects). The behavior is like [Combination of CM and DCM](#combination-of-cm-and-dcm).\n    - When you have a [sparse array](https://www.oreilly.com/library/view/javascript-the-definitive/9781449393854/ch07s03.html#:~:text=A%20sparse%20array%20is%20one,than%20the%20number%20of%20elements.) (WHY?) If it is not too spare, it’ll still be backed by an array, with empty array indices replaced with a ‘hole’ value. If an array is very sparse, it’ll no longer be backed by an array in memory. Instead, it will be backed by a dictionary/hashtable (The key is typically stored as a string representation of the index, and the value is the element itself).\n\n#### RingBuffer\nA ring buffer is a specialized data structure implemented using an array. It is a static-sized buffer where read and write operations occur through two distinct pointers that iterate through the array in a circular manner.\n\n![Ring_buffer gif](files/RingBuffer_ManimCE_v0.17.3.gif)\n\n- `Basic operations` time complexity: Same as [Array](#array) with the following improvement:\n  - `insertAtFront` is `O(1)`\n  - `removeAtFront` is `O(1)`\n- `Good`: \n  - `accessAtRandomIndex`, `insert` operation.\n  - Bulk memory allocation (fast).\n  - If used with primitive types (Value types), no dynamic memory allocation cost.\n  - As it is fixed-size, we can map it to virtual memory layer memory page to make it super fast.\n- `Not good`:\n  - Fixed size.\n  - Write operations may fail if the frequency of writes exceeds the frequency of reads.\n- Programming Languages implementations:\n  - Cpp: Has no built-in implementation for RingBuffer. [Here](https://www.boost.org/doc/libs/1_77_0/doc/html/circular_buffer.html) is an implementation.\n  - Swift: Has no built-in implementation for RingBuffer. [Here](https://github.com/kodecocodes/swift-algorithm-club/blob/master/Ring%20Buffer/RingBuffer.swift) is an implementation.\n  - Python: Has no built-in implementation for RingBuffer. [Here](https://gist.github.com/edwintcloud/f998e15d839e17ebcae2b8e2bb1d8d8c) is an implementation.\n  - Java: Has no built-in implementation for RingBuffer. [Here](https://www.geeksforgeeks.org/java-program-to-implement-circular-buffer/) is an implementation.\n  - C#: Has no built-in implementation for RingBuffer. [Here](https://github.com/joaoportela/CircularBuffer-CSharp) is an implementation.\n  - JavaScript: Has no built-in implementation for RingBuffer. [Here](https://github.com/trevnorris/cbuffer) is an implementation.\n\n#### LinkedList\n![LinkedList](files/linked_list.drawio.svg)\n- `Basic operations` time complexity: Same as [Discontiguous Memory data structures](#discontiguous-memory-data-structures) with one improvement.\n  - `insertAtBack()` becomes `O(1)` because we keep track of tail.\n  - `removeAtBack()` stays `O(n)` because we have to iterate from head to index n-1 to remove n.\n- `Good`: \n  - `insertAtFront`, `removeAtFront`, `insertAtBack` operations. \n- `Not good`: \n  - `accessAtRandomIndex`, `removeAtBack`, `insertAtMiddle`, `removeAtMiddle` Operations. \n  - Dynamic memory allocation (slow).\n- Programming Languages implementations:\n  - Cpp: [forward_list](https://cplusplus.com/reference/forward_list/forward_list/).\n  - Swift: Has no built-in implementation for LinkedList. An implementation can be found [here](https://github.com/kodecocodes/swift-algorithm-club/blob/master/Linked%20List/LinkedList.swift).\n  - Python: Has no built-in implementation for LinkedList. An implementation can be found [here](https://github.com/M2skills/Linked-List-in-Python).\n  - Java: [LinkedList](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html) is [DoubleLinkedList](#doublelinkedlist).\n  - C#: [LinkedList](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1?view=net-7.0) is a [DoubleLinkedList](#doublelinkedlist).\n  - JavaScript: Has no built-in implementation for LinkedList. an implementation can be found [here](https://github.com/datastructures-js/linked-list).\n\n![LinkedList gif](files/LinkedList_ManimCE_v0.17.3.gif)\n\n#### FreeList\nAs you have noticed, one of the `Not Good`s of a LinkedList data structure is dynamic memory allocation. It means, whenever you need a new node, you have to create a new one dynamically using `new` keyword. Dynamic memory allocation is a heavy task. One way of resolving this issue is to use FreeLists. FreeLists can be thought of as a reservoir for the LinkedList nodes. One approach is to initialize a FreeList with a sequence of nodes and whenever you need a Node for your LinkedList, you get one from the FreeList instance and when you remove a Node from the LinkedList, you will not free the memory, but return it to the FreeList reservoir to be used again later. Another approach is the following implementation for LinkedListNode with a private static freelist.\n```Java\nclass LinkListNode\u003cE\u003e {      // Singly linked list node with freelist support\n    // Extensions to support freelists\n    private static LinkListNode freelist = null;                  // Freelist for the class\n    \n    private E value;       // Value for this node\n    private LinkListNode\u003cE\u003e next;    // Point to next node in list\n    // Constructors\n    LinkList(E it, LinkListNode\u003cE\u003e inn) { value = it; next = inn; }\n    LinkList(LinkListNode\u003cE\u003e inn) { value = null; next = inn; }\n\n    E element() { return value; }                        // Return the value\n    E setElement(E it) { return value = it; }            // Set element value\n    LinkListNode\u003cE\u003e next() { return next; }                     // Return next link\n    LinkListNode\u003cE\u003e setNext(LinkListNode\u003cE\u003e inn) { return next = inn; } // Set next link\n\n    // Return a new link, from freelist if possible\n    static \u003cE\u003e LinkListNode\u003cE\u003e get(E it, LinkListNode\u003cE\u003e inn) {\n      if (freelist == null) {\n        return new LinkListNode\u003cE\u003e(it, inn);                 // Get from \"new\"\n      }\n      LinkListNode\u003cE\u003e temp = freelist;                       // Get from freelist\n      freelist = freelist.next();\n      temp.setElement(it);\n      temp.setNext(inn);\n      return temp;\n    }\n\n    // Return a link node to the freelist\n    void release() {\n      value = null;   // Drop reference to the element\n      next = freelist;\n      freelist = this;\n    }\n  }\n```\n- `Not good`: \n  - Depending on the situations, we may have unused memory.\n\n\n#### DoubleLinkedList\n![DoubleLinkedList](files/double_linked_list.drawio.svg)\n\n- `Basic operations` time complexity: Same as [Discontiguous Memory data structures](#discontiguous-memory-data-structures) with two improvements:\n  - `insertAtBack()` becomes `O(1)`.\n  - `removeAtBack()` becomes `O(1)`. Now we have access to n-1 from n and we can remove the pointer to n from n-1.\n- `Good`: \n  - `insertAtFront`, `removeAtFront`, `insertAtBack`, `removeAtBack` operations. \n- `Not good`: \n  - `accessAtRandomIndex`, `insertAtMiddle` Operations. \n  - Dynamic memory allocation (slow). We can fix this issue using [FreeList](#freelist).\n  - High overhead of extra storage for the forward and back reference.\n- Programming Languages implementations:\n  - Cpp: [list](https://cplusplus.com/reference/list/list/) is doubly linkedList.\n  - Swift: Has no built-in implementation for DoubleLinkedList. An implementation can be found [here](https://gist.github.com/loromits/945039733a1da524c82860a48d65fcf6).\n  - Python: Has no built-in implementation for DoubleLinkedList. an implementation can be found [here](https://github.com/OmkarPathak/Data-Structures-using-Python/blob/master/Linked%20Lists/DoublyLinkedList.py).\n  - Java: [LinkedList](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html) is DoubleLinkedList.\n  - C#: [LinkedList](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1?view=net-7.0) is DoubleLinkedList.\n  - JavaScript:  Has no built-in implementation for DoubleLinkedList. An implementation can be found [here](https://github.com/jasonsjones/doubly-linked-list).\n\n![DoubleLinkedList gif](files/DoubleLinkedList_ManimCE_v0.17.3.gif)\n\n#### CircularLinkedList\n![CircularLinkedList](files/circular_linked_list.drawio.svg)\n- `Basic operations` time complexity: Same as [LinkedList](#linkedlist) with some more capabilities.\n  - We can traverse to a previous node\n  - We can traverse in loop.\n\n#### CircularDoubleLinkedList\n![CircularDoubleLinkedList](files/circular_double_linked_list.drawio.svg)\n- `Basic operations` time complexity: Same as [DoubleLinkedList](#doublelinkedlist) with some more capabilities.\n  - We can traverse to a previous node\n  - We can traverse in loop in both direction.\n\n#### Stack\nStack is a Last-In-First-Out(LIFO) data structure. Any data structure that is `Good` at insert/remove from one of the ends can be used as a container for Stack. Based on this, stacks can be implemented using [DynamicArray](#dynamicarray) (`Good` at add/remove from the back), [LinkedList](#linkedlist) (`Good` at add/remove from front), [DoubleLinkedList](#doublelinkedlist)(`Good` at add/remove from both front and back) and [Deque](#deque). Each implementation inherits `Good` and `Not Good` of the container data structure.\n\n![Stack](files/stack.drawio.svg)\n\n##### Stack via DynamicArray\n- `Basic operations` time complexity: Same as [DynamicArray:](#dynamicarray)\n- `Methods`:\n  - `push()`: `insertAtBack` on array container.\n  - `pop`: `removeAtBack` on array container.\n- `Good`: \n  - `push()` and `pop()` are `O(1)` operations.\n  - Bulk memory allocation for pointers.\n  - If used with primitive types (value types), no dynamic memory allocation cost.\n- `Not good`: \n  - New memory allocations and copy cost when internal array capacity is full. \n  - Has unused memory allocation based on growth strategy of the pointer array.\n- Programming Languages implementations:\n  - Cpp: [Stack](https://cplusplus.com/reference/stack/stack/). In CPP vector, deque and list(DoubleLinkedList) can be used as container for Stack.\n  - Swift: Has no Stack in standard library. an implementation can be found [here](https://github.com/kodecocodes/swift-algorithm-club/blob/master/Stack/Stack.swift). \n  - Python: Has no built-in Stack in standard library but [list](https://docs.python.org/3/tutorial/datastructures.html#using-lists-as-stacks) can be used as stack in python. An implementation can be found [here](https://github.com/sreejithc321/Stack-in-Python).\n  - Java: [Stack](https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html) is implemented with dynamic array.\n  - C#: [Stack](https://learn.microsoft.com/en-us/dotnet/api/system.collections.stack?view=net-7.0) is implemented with dynamic array as the container.\n  - JavaScript: has no built-in stack data structure. an implementation can be found [here](https://github.com/krishheii/javascript-stack).\n\n![Stack via array](files/Stack_Array_ManimCE_v0.17.3.gif)\n\n##### Stack via LinkedList\n- `Basic operations` time complexity: Same as [LinkedList](#linkedlist). We use Head of LinkedList to insert/remove.\n- `Methods`:\n  - `push()`: `insertAtFront` on LinkedList container.\n  - `pop`: `removeAtFront` on LinkedList container.\n- `Good`: \n  - `push()` and `pop()` are `O(1)` operations.\n- `Not good`: \n  - `accessAtRandomIndex` is `O(n)`.\n  - Dynamic memory allocation (slow).\n\n![Stack via linkedlist](files/Stack_LinkedList_ManimCE_v0.17.3.gif)\n\n##### Stack via deque\n[Deque](#deque) data structure can be implemented using [Deque via DoubleLinkedList](#deque-via-doublelinkedlist) or [Deque via Array](#deque-via-array). The [Deque](#deque) can serve as a container for a Stack due to its behavior. C++ default container for Stack is deque.\n\n#### Queue\nQueue data structure is First-In-First-Out. Every data structure that is `Good` at addAtFront and removeAtBack or vice versa can be used as a container for Queue data structure. [DoubleLinkedList](#doublelinkedlist)(`Good` at add/remove at both ends) can be used as the containers for Queue data structure. Also [RingBuffer](#ringbuffer) can be used for fixed size queues. [DynamicArray:](#dynamicarray) is not a good container for queue data structure because of `O(n)` for insert operation. We can amortize this complexity using [Queue via Double Stack (Stack via DynamicArray)](#queue-via-double-stack-stack-via-dynamicarray). Another approach is storing contents in multiple smaller arrays, allocating additional arrays at the beginning or end as needed. Indexing is implemented by keeping a dynamic array or a LinkedList containing pointers to each of the smaller arrays. In this case, the cost of inserting reduced from `O(n)` to the `O(small_array.length)`. This approach is used for [deque](#deque-via-array). \n\n![Queue](files/queue.drawio.svg)\n\n##### Queue via DoubleLinkedList\n- `Basic operations` time complexity: [DoubleLinkedList](#doublelinkedlist)\n- `Methods`:\n  - `enqueue()`: `insertAtFront` on DoubleLinkedList container.\n  - `dequeue()`: `removeAtBack` on DoubleLinkedList container. \n- `Good`: \n  -  `enqueue()` and `dequeue()` are `O(1)` operations.\n- `Not good`: \n  - `accessAtRandomIndex` operation.\n  - Extra memory for forward/backward pointers.\n  - Dynamic memory allocation (slow).\n- Programming Languages implementations:\n  - Cpp: [queue](https://cplusplus.com/reference/queue/queue/) in cpp can has deque or list (DoubleLinkedList) as the container. the default container is deque.\n  - Swift: Has no built-in implementation for Queue. An implementation can be found [here](https://gitlab.com/agostini.tech/ATQueue).\n  - Python: Has no built-in implementation for Queue but [list](https://docs.python.org/3/tutorial/datastructures.html#using-lists-as-queues) can be used as queue in python. An implementation can be found [here](https://www.geeksforgeeks.org/python-queue-using-doubly-linked-list/).\n  - Java: [LinkedList](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html) and [ArrayDeque](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html) have implemented Queue interface.\n  - C#:[Queue](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1?view=net-7.0) in c# uses circular buffer array.\n  - JavaScript: an implementation can be found [here](https://github.com/datastructures-js/queue).\n\n![Queue via doublelinkedlist](files/Queue_DoubleLinkedList_ManimCE_v0.17.3.gif)\n\n##### Queue via RingBuffer\n- `Basic operations` time complexity: [RingBuffer](#ringbuffer)\n- `Methods`:\n  - `enqueue()`: `insertAtRandomIndex` on Array container.\n  - `dequeue()`: `accessAtRandomIndex` on Array container. \n- `Good`: \n  -  `enqueue()` and `dequeue()` are `O(1)` operations.\n  -  If used for primitive types (value types), No dynamic allocation.\n- `Not good`: \n  - Fixed size, `enqueue()` may fail.\n- Programming Languages implementations:\n  - C#: [Queue](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1?view=net-7.0) in c# uses circular buffer array.\n\n![Queue via ringbuffer](files/Queue_RingBuffer_ManimCE_v0.17.3.gif)\n\n##### Queue via Double Stack\nIf we use [DynamicArray](#dynamicarray) as container for our queue, the `dequeue()` time complexity would be `O(n)` (Adding items to start of an array is an `O(n)` operation ). But we can amortize this complexity to `O(1)` using two stacks. LeftStack for `enqueue()` and the RightStack for `dequeue()`. Each time the LeftStack is empty, copy the RightStack contents to the LeftStack. This operation guarantees First-In-First-Out for the queue.\n- `Basic operations` time complexity: Similar to [Stack via DynamicArray](#stack-via-dynamicarray).\n- `Methods`:\n  - `enqueue()`: `insertAtBack` on left Array container (the enqueue stack).\n  - `dequeue()`: `removeAtBack` on right Array container (the dequeue stack).\n- `Good`: \n  -  `enqueue()` and `dequeue()` are `O(1)` operations.\n  -  If used for primitive types (value types), No dynamic allocation.\n- `Not good`: \n  - New memory allocations and copy cost when capacity is full. \n  - Has unused memory allocation based on growth strategy.\n\n![Queue via doubleStack](files/Queue_DoubleStack_ManimCE_v0.17.3.gif)\n\n##### Deque as Queue\n\n[Deque (Double-Ended Queue)](#deque) can be used as Queue.\n\n#### Deque\nDeque (Double-Ended Queue) are a type of Queue that `enqueue()` and `dequeue()` can happen at both ends. Every data structure that is `Good` at insert/remove from both ends can be used as a container for Deque data structure. The only data structure that fullfil this requirement is [DoubleLinkedList](#doublelinkedlist). [Array](#array) is not a good data structure for implementing Deque data structure directly. However we can use some tricks to use [Array](#array) as a container for Deque data structure. See [Deque via Array](#deque-via-array).\n\n![Deque](files/deque.drawio.svg)\n\n##### Deque via DoubleLinkedList\nImplementing a Deque via [DoubleLinkedList](#doublelinkedlist) is straightforward as this data structure has `O(1)` for insertAtFront/removeAtFront and insertAtBack/removeAtBack operations.\n- `Methods`:\n  - `pushBack()`: insertAtBack of the DoubleLinkedList container.\n  - `pushFront()`: insertAtFront of the DoubleLinkedList container.\n  - `popBack()`: removeAtBack of the DoubleLinkedList container.\n  - `popFront()`: removeAtFront of the DoubleLinkedList container.\n- `Good`:\n  - Easy implementation\n- `Not Good`:\n  - Random access operation. \n  - Dynamic memory allocation (slow).\n  - High overhead of extra storage for the forward and back references.\n- Programming Languages implementations:\n  - Python: [deque](https://docs.python.org/3/library/collections.html#collections.deque) uses DoubleLinkedList internally.\n\n![Deque doubleLinkedlist](files/Deque_DoubleLinkedList_ManimCE_v0.17.3.gif)\n\n##### Deque via Array\nAs it was the case for Queue data structure, [Array](#array) cannot be used as a container for Deque data structure directly because insertAtFront/removeAtFront operations are not `O(1)` for Arrays. We can use one of the following techniques to use [Array](#array) as a container:\n1. Using a special [RingBuffer](#ringbuffer).\n2. Using an Array and allocating deque contents from the center of the underlying array, and resizing the underlying array when either end is reached.\n3. Storing contents in multiple smaller arrays, allocating additional arrays at the beginning or end as needed. Indexing is implemented by keeping a dynamic array containing pointers to each of the smaller arrays. In this case, the cost of resizing the array in step 2 is eliminated but different small arrays are not allocated contiguously in memory.\n\n\n- `Good`:\n  - Random Access operation\n- `Not Good`\n  - More complex implementation\n  - Need for array resize when filled\n- Programming Languages implementations:\n  - Cpp: [Deque](https://cplusplus.com/reference/deque/deque/) uses approach 3 of above mentioned tricks to use [Array](#array) as container for Deque. In this approach data is stored in smaller arrays and these arrays are linked using a doubleLinkedList or another array.\n  - Swift: Has no built-in implementation for LinkedList. An implementation can be found [here](https://github.com/kodecocodes/swift-algorithm-club/blob/master/Deque/Deque-Optimized.swift).\n  - Python: [deque](https://docs.python.org/3/library/collections.html#collections.deque) uses DoubleLinkedList internally.\n  - Java: [ArrayDeque](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html) is implemented using technique 1 of above mentioned tricks (Circular buffer).\n  - C#:[Deque](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1.dequeue?view=net-7.0) is implemented using technique 1 of above mentioned tricks (Circular buffer).\n  - JavaScript: An implementation can be found [here](https://github.com/montagejs/collections/blob/master/deque.js).\n\n![deque via ringbuffer](files/Deque_RingBuffer_ManimCE_v0.17.3.gif)\n\n#### PriorityQueue\nPriorityQueue is the same as [Queue](#queue) with one difference. The `dequeue` operation is not for the first item that has been inserted. Instead the dequeue item is selected based on a priority criteria and the item may be at the front, the middle or the end of the collection. Any data structure that is `Good` at inserting at one of the ends can be used as a container for PriorityQueue. As finding the item to be dequeued includes a searching phase, for linear data structures as the container for PriorityQueue the time complexity of dequeue operation is `O(n)`. In case of Heap data structure as the container, the time complexity reduces to `O(log(n))` due to internal structure of the Heap.\n\n![PriorityQueue](files/prority_queue.drawio.svg)\n\n##### PriorityQueue via DynamicArray\n- `Methods`:\n  - `enqueue()`: `insertAtBack` on Array container.\n  - `dequeue()`: iterate and then `removeAtMiddle` on Array container. Time complexity is `O(n)`.\n- `Good`: \n  -  `enqueue()` is `O(1)` operation.\n  -  If used for primitive types (value types), No dynamic allocation.\n- `Not good`: \n  - `dequeue()` operation is `O(n)`.\n  - New memory allocations and copy cost when capacity is full. \n  - Has unused memory allocation based on growth strategy.\n- Programming Languages implementations:\n  - Cpp: [priority_queue](https://cplusplus.com/reference/queue/priority_queue/) is using deque as a container by default. vector also can be used.\n\n##### PriorityQueue via LinkedList\n- `Methods`:\n  - `enqueue()`: `insertAtFront` on LinkedList container.\n  - `dequeue()`: iterate and then `removeAtMiddle` on LinkedList container. Time complexity is `O(n)`.\n- `Good`: \n  -  `enqueue()` is `O(1)` operation.\n- `Not good`: \n  - `dequeue()` operation is `O(n)`.\n  - Dynamic memory allocation (slow).\n\n\n##### PriorityQueue via Deque\n[Deque](#deque) data structure can be implemented using either [Deque via DoubleLinkedList](#deque-via-doublelinkedlist) or [Deque via Array](#deque-via-array) and PriorityQueue can use it as a container.\n\n##### PriorityQueue via BinaryHeap\n- `Methods`:\n  - `enqueue()`: `insert` on BinaryHeap container.\n  - `dequeue()`: `delete` on BinaryHeap container. \n- `Good`: \n  -  `dequeue()` is `O(log(n))` operation.\n- `Not good`: \n  - `enqueue` is `O(log(n))` operation. In [PriorityQueue via DynamicArray](#priorityqueue-via-dynamicarray) and [PriorityQueue via LinkedList](#priorityqueue-via-linkedlist) this operation is `O(1)`.\n- Programming Languages implementations:\n  - Java: [PriorityQueue](https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html) uses binary heap as internal data structure.\n  - C#:[PriorityQueue](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.priorityqueue-2?view=net-7.0)  uses binary heap as internal data structure.\n\n#### Associative collections\nAn associative collection is an abstract data type that stores a collection of (key, value) pairs, ensuring that each possible key appears at most once in the collection. However, there is no standardized naming convention for these types of data structures, leading to varying terminology across different programming languages, which can cause confusion. Some alternative names for associative collections include associative array, map, symbol table, or dictionary. See [here](https://en.wikipedia.org/wiki/Associative_array). \n\n##### UnorderedMap or HashTable\nOther name is HashTable. The main idea behind a Hashtable is to use a hashing function to map keys to specific buckets or slots in an array. Each bucket can store one or more key-value pairs. Hash functions can occasionally generate the same index for different keys, resulting in a collision. To handle collisions efficiently, Hashtable data structures employ various strategies:\n1. Each bucket in the array is a LinkedList of key-value pairs.\n2. [Open addressing](https://en.wikipedia.org/wiki/Open_addressing)\n3. Resizing the Array. \n\n ‌For most data structures, a linear search is an `O(n)` or `O(log(n))` operation. HashTable is a data structure with an amortized `O(1)` time complexity for searching. Length of arrays in a HashTable is a prime number.\n\n![HashTable](files/hash_table.drawio.svg)\n\n- `Good`:\n  - `O(1)` for search operation.\n- `Not Good`:\n  - Collection has no order. No Random access.\n  - If LinkedList used for collision handling: Worst-case for search can be `O(n)` (All nodes collide). Average-case is not `O(1)`.\n- Programming Languages implementations: \n  - CPP: [unordered_map](https://cplusplus.com/reference/unordered_map/unordered_map/) is an unordered collection created using HashTable. Another version is [unordered_multimap](https://cplusplus.com/reference/unordered_map/unordered_multimap/) that allows for repetitive keys. in the [unordered_map](https://cplusplus.com/reference/unordered_map/unordered_map/) version the keys are unique.\n  - Swift: [Dictionary](https://developer.apple.com/documentation/swift/dictionary) is an unordered collection created using HashTable. The keys are unique.\n  - Python: [dict](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict) is an unordered map created using HashTable. Also [Counter](https://docs.python.org/3/library/collections.html#collections.Counter) is a dictionary specific to counting of values (the key is the item you put in the dictionary and the value is a counter. on each insert, if the value exists, 1 is added to the count). [UserDict](https://docs.python.org/3/library/collections.html#collections.UserDict) is a wrapper class that allows you to create your own dictionary-like objects by inheriting from UserDict and implementing certain methods. It provides a convenient way to create custom dictionary-like classes without directly subclassing the built-in dict class. [mappingproxy](https://docs.python.org/3/library/types.html#types.MappingProxyType) object provides read-only access to the original dictionary's data.\n  - Java: [HashTable](https://docs.oracle.com/javase/8/docs/api/java/util/Hashtable.html) is unordered, thread-safe. [HashMap](https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html) is unordered map created using HashTable.\n  - C#: [Dictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?view=net-7.0) is an unordered map created using HashTable. [ListDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.specialized.listdictionary?view=net-7.0) uses a combination of array (for keys) and LinkedList (for values). Operations are all `O(n)` and it MUST be used for small collections (Less than 10 items). \n  - Javascript: [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) is an unordered map.\n\n##### OrderedMap via HashTable and LinkedList\nA collection of key-value pairs. While the order of the insertion is preserved, the collection is not sorted.\n![OrderedMap](files/ordered_map.drawio.svg)\n\n- `Good`:\n  - Order of the insertion is preserved. (Unlike SortedMap, the keys are not sorted.)\n  - `accessDataBySequence` is possible.\n- `Not Good`:\n  - No random access with `O(1)` because of LinkedList.\n  - High overhead of extra storage for the forward and back reference.\n- Programming Languages implementations: \n  - Python: [OrderedDic](https://docs.python.org/3/library/collections.html#ordereddict-objects) is implemented using a combination of a doubly linked list and a dictionary.\n  - Java: [LinkedHashMap](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html). In Java, the LinkedHashMap class uses a combination of a hash table and a doubly linked list as its internal data structure to provide the functionality of a hash map with predictable iteration order.\n  - C#: [OrderedDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.specialized.ordereddictionary?view=net-7.0) uses a combination of a HashTable and an ArrayList. \n\n##### OrderedMap via HashTable and DynamicArray\nA collection of key-value pairs. While the order of the insertion is preserved, the collection is not sorted.\n![OrderedMap via array](files/ordered_map_array_version.drawio.svg)\n\n- `Good`:\n  - Order of the insertion is preserved. (Unlike SortedMap, the keys are not sorted.)\n  - `accessDataBySequence` is possible.\n  - `accessDataAtRandomIndex` is `O(1)`.\n- `Not Good`:\n  - insert is `O(n)` because of array.\n  - remove is `O(n)` because of array.\n- Programming Languages implementations: \n  - C#: [OrderedDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.specialized.ordereddictionary?view=net-7.0) uses a combination of a HashTable and an ArrayList. \n\n##### SortedMap via Self Balancing Tree\nA collection of key-value pairs which is sorted by the key.\n- `Good`:\n  - Search is `O(log(n))`\n  - keys are sorted.\n- `Not Good`:\n  - Random access is not `O(1)`.\n  - Suitable for small number of data.\n- Programming Languages implementations:\n  - CPP: [map](https://cplusplus.com/reference/map/map/) uses Red-Black Tree for implementation. Another version is [multimap](https://cplusplus.com/reference/map/multimap/) which allows duplicate keys. In the [map](https://cplusplus.com/reference/map/map/) version, keys are unique.\n  - Swift: Swift has no built-in Ordered map using tree data structure. You can sort the keys of a dictionary to a collection and iterate that collection.\n  - Python: Swift has no built-in Ordered map using tree data structure.\n  - Java: [TreeMap](https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html) is implemented using a Red-Black Tree as its internal data structure.\n  - C#: [SortedDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.sorteddictionary-2?view=net-7.0) is implemented internally using a self-balancing binary search tree called a Red-Black Tree. [SortedList](https://learn.microsoft.com/en-us/dotnet/api/system.collections.sortedlist?view=net-7.0) uses two separate arrays. one for the keys and the second for the values. As the array for the keys is sorted, when a new item is inserted, the index is found via binary search. The time complexity for inserting is `O(n)`. Binary search is `O(log(n))`and the items re-arrangement is `O(n)`.\n  - JavaScript: an implementation can be found [here](https://github.com/somdipdey/JavaScript-implementation-of-java.util.TreeMap-Class).\n\n#### Set\n##### UnorderedSet\nIt is almost exactly like [UnorderedMap or HashTable](#unorderedmap-or-hashtable) with the distinction that the node has only a key and no value exists. In Java, it is implemented using HashTable and the values for the nodes are set to a fixed value.\n- `Good`:\n  - `O(1)` for search operation.\n- `Not Good`:\n  - Collection has no order. No Random access.\n  - If LinkedList used for collision handling: Worst-case for search can be `O(n)`. Average-case is not `O(1)`.\n- Programming Languages implementations:\n  - CPP: [unordered_set](https://cplusplus.com/reference/unordered_set/unordered_set/) is an unordered collection created using HashTable. Another version is [unordered_multiset](https://cplusplus.com/reference/unordered_set/unordered_multiset/) that allows for duplicate keys. in the [unordered_set](https://cplusplus.com/reference/unordered_set/unordered_set/) version the keys are unique.\n  - Swift: [Set](https://developer.apple.com/documentation/swift/set) is an unordered collection created using HashTable. The keys are unique.\n  - Python: [Set](https://docs.python.org/3/tutorial/datastructures.html#sets) is an unordered set created using HashTable. [frozenset](https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset) is an immutable set.\n  - Java: [HashSet](https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html) is an unordered set created using HashTable.\n  - C#: [HashSet](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1?view=net-7.0)  is an unordered set created using HashTable.\n  - Javascript: [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) is an unordered set.\n\n##### OrderedSet via HashTable and LinkedList\nIt is almost exactly like [OrderedMap via HashTable and LinkedList](#orderedmap-via-hashtable-and-linkedlist) with the distinction that the node has only a key and no value exists. In Java, it is implemented using HashTable and the values for the nodes are set to a fixed value.\n- `Good`:\n  - Order of the insertion is preserved. (Unlike SortedSet, the keys are not sorted.)\n- `Not Good`:\n  - No random access with `O(1)` because of LinkedList.\n- Programming Languages implementations:\n  - Java: [LinkedHashSet](https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashSet.html). In Java, the LinkedHashSet class uses a combination of a hash table and a doubly linked list as its internal data structure to provide the functionality of a hash set with predictable iteration order.\n\n\n##### SortedSet via Self Balancing Tree\n- `Good`:\n  - Search is `O(log(n))`\n  - keys are sorted.\n- `Not Good`:\n  - Random access is not `O(1)`.\n  - Suitable for small number of data.\n- Programming Languages implementations:\n  - CPP: [set](https://cplusplus.com/reference/set/set/) uses Red-Black Tree for implementation. Another version is [multiset](https://cplusplus.com/reference/set/multiset/) which allows duplicate keys. In the [Set](https://cplusplus.com/reference/set/set/) version, keys are unique.\n  - Swift: Swift has no built-in Ordered set. You can sort the keys of a set to a collection and iterate that collection.\n  - Python: Python has no built-in Ordered set. \n  - Java: [TreeSet](https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html) is implemented using a Red-Black Tree as its internal data structure.\n  - C#: [SortedSet](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.sortedset-1?view=net-7.0) is implemented internally using a self-balancing binary search tree called a Red-Black Tree.\n  - JavaScript: An implementation can be found [here](https://github.com/mljs/tree-set).\n\n#### SkipList\n\n\n---\n\n\n#### standard library data structures\n\n##### C++\n\n![Cpp dsa](files/Cpp_DS\u0026A_Hierarchy.drawio.svg)\n\n##### Swift\nSwift source code for collections can be found [here](https://github.com/apple/swift/tree/main/stdlib/public/core).\n![Swift ds diagram](files/Swift_DS\u0026A_Hierarchy.drawio.svg)\n\n##### CSharp\nDotnet source code for collections can be found [here](https://github.com/dotnet/runtime/tree/f175acf52f1e793892ef9d9fea632f3624d50479/src/libraries/System.Private.CoreLib/src/System/Collections).\n\n![C# ds diagram](files/Dotnet_DS\u0026A_Hierarchy.drawio.svg)\n\n##### Python\nSource code for python built-in types can be found [here](https://github.com/python/cpython/blob/main/Objects). Collection module source code is located [here](https://github.com/python/cpython/blob/3.11/Lib/collections/__init__.py).\n\n![python dsa](files/Python_DS\u0026A_Hierarchy.drawio.svg)\n\n##### Java\nJava collections source code is located [here](https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/java/util).\n\n![Java ds diagram](files/Java_DS\u0026A_Hierarchy.drawio.svg)\n\n\n---\n\n### Non-Linear structures\nFrom a mathematical standpoint, LinkedLists can be regarded as a particular variation of graphs. However, graphs encompass more intricate structures, commonly referred to as trees and graph data structures, within the realm of programming.\n\n#### Tree\nIn the context of data structures and algorithms, a \"tree\" refers to a hierarchical data structure composed of nodes connected by edges. Common elements of a tree are depicted in the following picture.\n\n![Tree](files/tree.png)\n\n- Memory representation\u003cbr\u003e\n Linear data structures can be represent in memory either like [Contiguous Memory](#contiguous-memory-data-structures),  [Dis-contiguous memory data structures](#discontiguous-memory-data-structures) or a [Combination of both (Array of pointers)](#combination-of-cm-and-dcm). In case of non-linear data structures like Trees we use the same concepts to represent the data in the memory. Each memory representation has it's own pros and cons.\n  -  `Linked representation`:  In this representation, each node of the tree is represented as an object or struct that contains the data and references (pointers) to its children or parent nodes. This representation allows for flexible tree structures but may require additional memory for storing the pointers.\n  - `Array representation`: The elements of the array correspond to the values of the tree. The relationship between nodes is determined by the indices of the array elements. This representation is simple and memory-efficient but may require resizing the array for dynamic trees and the implementation is possible for trees with fixed numbers of children like k-ary and binary trees.\n  - `Array of pointers representation`: The elements of the array correspond to the nodes of the tree. Depending on the implementation, nodes hold different information.\n- Types of trees based on the number of the child nodes.\n  - n-ary trees (general trees) or the trees with arbitrary number of children per node.\n  - k-ary trees or the trees with maximum number of k children per node.\n    - k == 2: Binary trees.\n- Fundamental operations\u003cbr\u003e\n[Fundamental operations](#fundamental-operations) in linear data structures are typically straightforward in terms of their implementation and functionality. For example, in [Array](#array) the `accessDataBySequence()` operation can be achieved by iterating from the start index to the end index of the array. For [LinkedList](#linkedlist) this operation is done by iterating from the head toward the end of the list. The order of the data-blocks in an array is implicitly determined by the order of them in the contiguous memory and start and end indices are the start and the end of the array. In case of LinkedLists the order of the nodes are determined explicitly by pointers from one node to the next one and the start and end indices are head and tail of the LinkedList. But imagine a Tree data structure like above picture. How you iterate over the nodes? Where is the start index and where is the end index? What is the order of the nodes? `Fundamental operations` for Trees are not as straightforward as for linear data structures. Depending on the `implementation` and the `memory representation` of a tree, fundamental operations for trees can be achieved differently.\n  - `accessDataBySequence()`:\n    - Depth-First traversal\n      - PreOrder traversal: ParentNode -\u003e Left -\u003e Right (NLR)\n      - InOrder traversal: Left -\u003e ParentNode -\u003e Right (LNR). Applicable for BinaryTree.\n      - PostOrder traversal: Left -\u003e Right -\u003e ParentNode (LRN)\n    - Breadth-first traversal\n      - level-order traversal\n  - `accessAtRandomIndex()`\n  - `insertAtRandomIndex()`\n  - `removeAtRandomIndex()`\n\n ![Tree traversal](files/tree%20traversal.drawio.svg)\n\n##### General Tree\nA `general tree`, also known as an `n-ary tree`, is a hierarchical tree structure where each node can have an arbitrary number of child nodes. There are several `representations` for general trees:\n- List of children: DynamicArray of TreeNodes. Children are a LinkedList of TreeNodes indices.\n  ![Dynamic array of TreeNode](files/List%20of%20children%20DynamicArray%20of%20TreeNode.drawio.svg)\n    ```swift\n    public class ChildIndex {\n      var index: Int\n      var next: ChildIndex?\n    }\n    public struct TreeNode\u003cT\u003e {\n      var value: T\n      var children: ChildIndex?\n    }\n    var tree: [TreeNode] = []\n    ```\n- List of children: LinkedList of TreeNodes. Children are a dynamicArray of pointers of TreeNodes\n  ![LinkedList of DynamicArray of children](files/List%20fo%20children%20LinkedList%20of%20dynamicArray%20of%20children.drawio.svg)\n    ```swift\n    public class TreeNode\u003cT\u003e {\n      public var value: T\n      public var children: [TreeNode\u003cT\u003e]\n    }\n    ```\n- List of children: LinkedList of TreeNodes. Children are LinkedList of pointers.\n  ![LinkedList fo children](files/List%20fo%20children%20LinkedList%20of%20children.drawio.svg)\n    ```swift\n    public class ChildPointer\u003cT\u003e {\n      var node: TreeNode\u003cT\u003e\n      var next: ChildPointer\u003cT\u003e?\n    }\n    public class TreeNode\u003cT\u003e {\n      var value: T\n      // A linkedlist of children\n      var children_head:ChildPointer\u003cT\u003e?\n    }\n    \n    var tree: TreeNode = TreeNode(value: 0)\n    //...\n    ```\n- Left-Child, Right-sibling: Array of TreeNodes\n  ![Left child right sibling](files/Left%20child%20right%20sibling.drawio.svg)\n    ```swift\n    public struct TreeNode\u003cT\u003e {\n      public var value: T\n      public var LeftChildIndex: Int\n      public var ParentIndex: Int\n      public var RightSiblingIndex: Int\n    }\n    ```\n- Dynamic Left-Child, Right-Sibling: LinkedList of TreeNodes\u003cbr\u003e\n  ![Dynamic Left-Child, Right-Sibling](files/dynamic%20left%20child%20right%20sibling.drawio.svg)\n    ```swift\n    public class TreeNode\u003cT\u003e {\n      public var value: T\n      public var LeftChild: TreeNode\u003cT\u003e?\n      public var RightSibling: TreeNode\u003cT\u003e?\n    }\n    ```\n- Parent pointer\u003cbr\u003e\n  ![Parent pointer](files/parent%20pointer.drawio.svg)\n\n\nEach of above representations can be useful for a specific type of problem. For example, to answer the question \"Given two nodes, are they in the same tree?\", the best representation is Parent pointer. Also this representation is used to save tress in the SQL databases. We can use algorithmic methods to convert between different representations. Regarding fundamental operations, depending on the representation, these operations can be implemented differently for general trees.\n\n##### k-ary Tree\nTrees with a maximum number of children per nodes are called k-ary trees. Other than the above `representations` for general trees which are also applicable here, k-ary trees can be represented in a more memory-efficient way using arrays. Please note that array representation is not suitable for insert/remove operations.\n- Array representation\n  \n  ![Array representation](files/k-ary%20tree%20array%20representation.drawio.svg)\n\nIf k == 2, then the tree is called BinaryTree.\n\n##### BinaryTree\nBinary trees are a special kind of k-ary trees with k = 2 (the trees with maximum two children per node). This types of trees can easily be represented with both LinkedList or Array representations. Binary trees serve as the basis for many tree structures and algorithms. \n\n![Binary tree types](files/binarytree%20types.drawio.svg)\n\nThe most common way for representing dynamic binary trees is LinkedList representation.\n```swift\n  public class BinaryNode\u003cT\u003e {\n    public var value: T\n    public var leftChild: BinaryNode?\n    public var rightChild: BinaryNode?\n  }\n``` \n\n- `Fundamental operations`:\n  - `accessDataBySequence()`\n    - Depth-First traversal\n      - PreOrder traversal: ParentNode -\u003e Left -\u003e Right (NLR)\n        ```swift\n        extension BinaryNode {\n          public func traversePreOrder(visit: (T) -\u003e Void) {\n            visit(value)\n            leftChild?.traversePreOrder(visit: visit)\n            rightChild?.traversePreOrder(visit: visit)\n          }\n        }\n        ```\n      - InOrder traversal: Left -\u003e ParentNode -\u003e Right (LNR)\n      ```swift\n      extension BinaryNode {\n        public func traverseInOrder(visit: (T) -\u003e Void) {\n          leftChild?.traverseInOrder(visit: visit)\n          visit(value)\n          rightChild?.traverseInOrder(visit: visit)\n        }\n      }\n      ```\n      - PostOrder traversal: Left -\u003e Right -\u003e ParentNode (LRN)\n      ```swift\n      extension BinaryNode {\n        public func traversePreOrder(visit: (T) -\u003e Void) {\n          visit(value)\n          leftChild?.traversePreOrder(visit: visit)\n          rightChild?.traversePreOrder(visit: visit)\n        }\n      }\n      ```\n    - Breadth-first traversal\n      - level-order traversal\n      ```swift\n      extension BinaryNode {\n        public func forEachLevelOrder(visit: (BinaryNode?) -\u003e Void) {\n        visit(self)\n        var queue = Queue\u003cBinaryNode?\u003e()\n        queue.enqueue(leftChild)\n        queue.enqueue(rightChild)\n        while let node = queue.dequeue() {\n            visit(node)\n            queue.enqueue(node.leftChild)\n            queue.enqueue(node.rightChild)\n          }\n        }\n      }\n      ```\n\n###### BinarySearchTree\nBinarySearchTree is special type of BinaryTree with two rules:\n- The value of the left child must be less then the value of the parent\n- The value of the right child must be bigger or equal to the parent value.\n\n![BinarySearchTree](files/binary%20search%20tree.drawio.svg)\n\nFor dynamic BinarySearchTree (with insert/remove) we use LinkedList representation.\n\nAlgorithms:\n- accessDataBySequence():\n  - in-order traversal: See [BinaryTree](#binarytree)\n  - pre-order traversal: See [BinaryTree](#binarytree)\n  - post-order traversal: See [BinaryTree](#binarytree)\n- insert: We search(using either of the traversal algorithms) and then insert the value. Time complexity for the search is `O(log(n))` for balanced trees.\n- remove: We search(using either of the traversal algorithms) and then insert the value. Time complexity for the search is `O(log(n))` for balanced trees.\n- search: We search using either of the traversal algorithms. Time complexity for the search is `O(log(n))` for balanced trees. for unbalanced trees, the time complexity becomes `O(n)`.\n\nIf a BinarySearchTree becomes unbalanced, the time complexity of operations degrade from `O(log(n))` to `O(n)`. To resolve this issue, self-balancing trees like [AVLTree](#avltree), [Red Black Tree](#redblacktree) and [B Tree](#b-tree) are introduced. The AVL trees are more balanced compared to Red-Black Trees, but they may cause more rotations during insertion and deletion. So if your application involves frequent insertions and deletions, then Red-Black trees should be preferred. And if the insertions and deletions are less frequent and search is a more frequent operation, then AVL tree should be preferred over the Red-Black Tree. B-Trees are characterized by the large number of keys that they can store in a single node, which is why they are also known as “large key” trees. Each node in a B-Tree can contain multiple keys, which allows the tree to have a larger branching factor and thus a shallower height. This shallow height leads to less disk I/O, which results in faster search and insertion operations.\n\n###### AVLTree\nIf a BinarySearchTree becomes unbalanced, the time complexity of operations all degrade from `O(log(n))` to `O(n)`. To resolve this issue self-balancing BinarySearchTrees have been introduced. One of them is AVL Tree. This BinarySearchTree keep itself balanced via self-balancing algorithms. Keeping the tree balanced guarantees the time complexity of operations to be `O(log(n))`.\n\nAlgorithms:\n- accessDataBySequence():\n  - in-order traversal: See [BinarySearchTree](#binarysearchtree)\n  - pre-order traversal: See [BinarySearchTree](#binarysearchtree)\n  - post-order traversal: See [BinarySearchTree](#binarysearchtree)\n- insert: The insertion for [BinarySearchTree](#binarysearchtree) is changed to include the self-balancing algorithm so that the insertion does not make the tree unbalanced.\n- remove: The removal for [BinarySearchTree](#binarysearchtree) is changed to include the self-balancing algorithm so that the removal does not make the tree unbalanced.\n- search: See [BinarySearchTree](#binarysearchtree)\n- balancing algorithms.\n  - left-Rotation\n  - right-rotation\n  - left-right rotation\n  - right-left rotation\n\n###### RedBlackTree\nIf a BinarySearchTree becomes unbalanced, the time complexity of operations all degrade from `O(log(n))` to `O(n)`. To resolve this issue self-balancing BinarySearchTrees have been introduced. One of them is RedBlackTree. This BinarySearchTree keep itself balanced via self-balancing algorithms. Keeping the tree balanced guarantees the time complexity of operations to be `O(log(n))`. The rules by which the tree is kept balanced by RedBlackTree are:\n1. Every node has a color either red or black.\n2. The root of the tree is always black.\n3. There are no two adjacent red nodes (A red node cannot have a red parent or red child).\n4. Every path from a node (including root) to any of its descendants NULL nodes has the same number of black nodes.\n5. Every leaf (e.i. NULL node) must be colored BLACK.\n\n###### B Tree\nIf a BinarySearchTree becomes unbalanced, the time complexity of operations all degrade from `O(log(n))` to `O(n)`. To resolve this issue self-balancing BinarySearchTrees have been introduced. One of them is B-Tree. This BinarySearchTree keep itself balanced via self-balancing algorithms. Keeping the tree balanced guarantees the time complexity of operations to be `O(log(n))`. Unlike traditional binary search trees, B-Trees are characterized by the large number of keys that they can store in a single node, which is why they are also known as “large key” trees. Each node in a B-Tree can contain multiple keys, which allows the tree to have a larger branching factor and thus a shallower height. This shallow height leads to less disk I/O, which results in faster search and insertion operations.\n\n###### Splay Tree\nA splay tree is a binary search tree with the additional property that recently accessed elements are quick to access again. Like self-balancing binary search trees, a splay tree performs basic operations such as insertion, look-up and removal in O(log n) amortized time. To keep itself organized, Splay Tree uses the following self-organizing algorithms.\n1. Zig Rotation\n2. Zag Rotation\n3. Zig – Zig Rotation\n4. Zag – Zag Rotation\n5. Zig – Zag Rotation\n6. Zag – Zig Rotation\n\n###### KD Tree\nA K-D Tree(also called as K-Dimensional Tree) is a binary search tree where data in each node is a K-Dimensional point in space. In short, it is a space partitioning(details below) data structure for organizing points in a K-Dimensional space.\n\n###### HeapTree\nAlgorithms:\n- insert\n- remove\n- remove(at: )\n- findIndexOf(:)\n\n###### Cartesian Tree\n\n###### Fibonacci Heap\n\n\n###### Segment Tree\n\n###### Merkle Tree\na hash tree or Merkle tree is a tree in which every \"leaf\" (node) is labelled with the cryptographic hash of a data block, and every node that is not a leaf (called a branch, inner node, or inode) is labelled with the cryptographic hash of the labels of its child nodes. A hash tree allows efficient and secure verification of the contents of a large data structure. A hash tree is a generalization of a hash list and a hash chain.\n\n##### Trie\nAlgorithms:\n- insert\n- contain\n- remove\n- hasPrefix\n\n#### Graph\nVertex, Edge, ...\nRepresentation:\n- AdjacencyList:\n  - Algorithms:\n    - addvertex\n    - addEdge\n    - findEdge\n    - findWeight\n- Adjacency matrix\n  - Algorithms:\n    - addvertex\n    - addEdge\n    - findEdge\n    - findWeight\n\nAlgorithms:\n- Search:\n  - BreadthFirstSearch:\n  - Depth-First Search: \n  - Dijkstra’s Algorithm (Path finding): \n  - Prim’s Algorithm (minimum spanning tree)\n\n\n---\n\n## Augmented data structures\n\n### Algorithms\n\nComing soon","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhaledhosseini%2Fpolygolt-dsa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkhaledhosseini%2Fpolygolt-dsa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhaledhosseini%2Fpolygolt-dsa/lists"}