In computer science , a dynamic array , growable array , resizable array , dynamic table , mutable array , or array list is a random access , variable-size list data structure that allows elements to be added or removed. It is supplied with standard libraries in many modern mainstream programming languages . Dynamic arrays overcome a limit of static arrays , which have a fixed capacity that needs to be specified at allocation .
65-414: A dynamic array is not the same thing as a dynamically allocated array or variable-length array , either of which is an array whose size is fixed when the array is allocated, although a dynamic array may use such a fixed-size array as a back end. A simple dynamic array can be constructed by allocating an array of fixed-size, typically larger than the number of elements immediately required. The elements of
130-485: A linked list is a linear collection of data elements whose order is not given by their physical placement in memory. Instead, each element points to the next. It is a data structure consisting of a collection of nodes which together represent a sequence . In its most basic form, each node contains data , and a reference (in other words, a link ) to the next node in the sequence. This structure allows for efficient insertion or removal of elements from any position in
195-414: A "first" and "last" node. An empty list is a list that contains no data records. This is usually the same as saying that it has zero nodes. If sentinel nodes are being used, the list is usually said to be empty when it has only sentinel nodes. The link fields need not be physically part of the nodes. If the data records are stored in an array and referenced by their indices, the link field may be stored in
260-416: A 'value' field as well as 'next' field, which points to the next node in line of nodes. Operations that can be performed on singly linked lists include insertion, deletion and traversal. The following C language code demonstrates how to add a new node with the "value" to the end of a singly linked list: In a 'doubly linked list', each node contains, besides the next-node link, a second link field pointing to
325-466: A dynamic array algorithm called tiered vectors that provides O ( n ) performance for insertions and deletions from anywhere in the array, and O ( k ) get and set, where k ≥ 2 is a constant parameter. Hashed array tree (HAT) is a dynamic array algorithm published by Sitarski in 1996. Hashed array tree wastes order n amount of storage space, where n is the number of elements in the array. The algorithm has O (1) amortized performance when appending
390-513: A linear initial segment. Algorithms for searching or otherwise operating on these have to take precautions to avoid accidentally entering an endless loop. One well-known method is to have a second pointer walking the list at half or double the speed, and if both pointers meet at the same node, a cycle has been found. Sentinel node may simplify certain list operations, by ensuring that the next or previous nodes exist for every element, and that even empty lists have at least one node. One may also use
455-560: A linked list while permitting much more efficient indexing, taking O(log n) time instead of O(n) for a random access. However, insertion and deletion operations are more expensive due to the overhead of tree manipulations to maintain balance. Schemes exist for trees to automatically maintain themselves in a balanced state: AVL trees or red–black trees . While doubly linked and circular lists have advantages over singly linked linear lists, linear lists offer some advantages that make them preferable in some situations. A singly linked linear list
520-479: A list by a handle that consists of two links, pointing to its first and last nodes. The alternatives listed above may be arbitrarily combined in almost every way, so one may have circular doubly linked lists without sentinels, circular singly linked lists with sentinels, etc. As with most choices in computer programming and design, no method is well suited to all circumstances. A linked list data structure might work well in one case, but cause problems in another. This
585-466: A much smaller constant. Naïve resizable arrays and linearly growing arrays may be useful when a space-constrained application needs lots of small resizable arrays; they are also commonly used as an educational example leading to exponentially growing dynamic arrays. C++ 's std::vector and Rust 's std::vec::Vec are implementations of dynamic arrays, as are the ArrayList classes supplied with
650-461: A pointer to any node serves as a handle to the whole list. With a circular list, a pointer to the last node gives easy access also to the first node, by following one link. Thus, in applications that require access to both ends of the list (e.g., in the implementation of a queue), a circular structure allows one to handle the structure by a single pointer, instead of two. A circular list can be split into two circular lists, in constant time, by giving
715-623: A rudimentary support for resizable vectors by allowing to configure the built-in array type as adjustable and the location of insertion by the fill-pointer . Dynamic memory allocation Too Many Requests If you report this error to the Wikimedia System Administrators, please include the details below. Request from 172.68.168.226 via cp1108 cp1108, Varnish XID 229113973 Upstream caches: cp1108 int Error: 429, Too Many Requests at Thu, 28 Nov 2024 08:28:06 GMT Linked list In computer science ,
SECTION 10
#1732782486673780-400: A sentinel node at the end of the list, with an appropriate data field, to eliminate some end-of-list tests. For example, when scanning the list looking for a node with a given value x , setting the sentinel's data field to x makes it unnecessary to test for end-of-list inside the loop. Another example is the merging two sorted lists: if their sentinels have data fields set to +∞, the choice of
845-491: A separate array with the same indices as the data records. Since a reference to the first node gives access to the whole list, that reference is often called the 'address', 'pointer', or 'handle' of the list. Algorithms that manipulate linked lists usually get such handles to the input lists and return the handles to the resulting lists. In fact, in the context of such algorithms, the word "list" often means "list handle". In some situations, however, it may be convenient to refer to
910-415: A separate case. In the last node of a linked list, the link field often contains a null reference, a special value is used to indicate the lack of further nodes. A less common convention is to make it point to the first node of the list; in that case, the list is said to be 'circular' or 'circularly linked'; otherwise, it is said to be 'open' or 'linear'. It is a list where the last node pointer points to
975-412: A series of objects to the end of a hashed array tree. In a 1999 paper, Brodnik et al. describe a tiered dynamic array data structure, which wastes only n space for n elements at any point in time, and they prove a lower bound showing that any dynamic array must waste this much space if the operations are to remain amortized constant time. Additionally, they present a variant where growing and shrinking
1040-438: A small fixed additional overhead for storing information about the size and capacity. This makes dynamic arrays an attractive tool for building cache -friendly data structures . However, in languages like Python or Java that enforce reference semantics, the dynamic array generally will not store the actual data, but rather it will store references to the data that resides in other areas of memory. In this case, accessing items in
1105-541: A space-time trade-off and algorithms used in the memory allocator itself. For growth factor a , the average time per insertion operation is about a /( a −1), while the number of wasted cells is bounded above by ( a −1) n . If memory allocator uses a first-fit allocation algorithm, then growth factor values such as a =2 can cause dynamic array expansion to run out of memory even though a significant amount of memory may still be available. There have been various discussions on ideal growth factor values, including proposals for
1170-518: A specific point of a list, assuming that a pointer is indexed to the node (before the one to be removed, or before the insertion point) already, is a constant-time operation (otherwise without this reference it is O(n)), whereas insertion in a dynamic array at random locations will require moving half of the elements on average, and all the elements in the worst case. While one can "delete" an element from an array in constant time by somehow marking its slot as "vacant", this causes fragmentation that impedes
1235-440: A thing makes sense) is a null pointer, indicating that the list has no nodes. Without this choice, many algorithms have to test for this special case, and handle it separately. By contrast, the use of null to denote an empty linear list is more natural and often creates fewer special cases. For some applications, it can be useful to use singly linked lists that can vary between being circular and being linear, or even circular with
1300-439: Is a recursive data structure, because it contains a pointer to a smaller object of the same type. For that reason, many operations on singly linked linear lists (such as merging two lists, or enumerating the elements in reverse order) often have very simple recursive algorithms, much simpler than any solution using iterative commands . While those recursive solutions can be adapted for doubly linked and circularly linked lists,
1365-452: Is a list of some of the common tradeoffs involving linked list structures. A dynamic array is a data structure that allocates all elements contiguously in memory, and keeps a count of the current number of elements. If the space reserved for the dynamic array is exceeded, it is reallocated and (possibly) copied, which is an expensive operation. Linked lists have several advantages over dynamic arrays. Insertion or deletion of an element at
SECTION 20
#17327824866731430-414: Is also faster than on linked lists on many machines, because they have optimal locality of reference and thus make good use of data caching. Another disadvantage of linked lists is the extra storage needed for references, which often makes them impractical for lists of small data items such as characters or Boolean values , because the storage overhead for the links may exceed by a factor of two or more
1495-415: Is expensive because it involves allocating a new underlying array and copying each element from the original array. Elements can be removed from the end of a dynamic array in constant time, as no resizing is required. The number of elements used by the dynamic array contents is its logical size or size , while the size of the underlying array is called the dynamic array's capacity or physical size , which
1560-469: Is mitigated by the gap buffer and tiered vector variants discussed under Variants below. Also, in a highly fragmented memory region, it may be expensive or impossible to find contiguous space for a large dynamic array, whereas linked lists do not require the whole data structure to be stored contiguously. A balanced tree can store a list while providing all operations of both dynamic arrays and linked lists reasonably efficiently, but both insertion at
1625-408: Is not feasible. Arrays have better cache locality compared to linked lists. Linked lists are among the simplest and most common data structures. They can be used to implement several other common abstract data types , including lists , stacks , queues , associative arrays , and S-expressions , though it is not uncommon to implement those data structures directly without using a linked list as
1690-430: Is not true with the other variants: a node may never belong to two different circular or doubly linked lists. In particular, end-sentinel nodes can be shared among singly linked non-circular lists. The same end-sentinel node may be used for every such list. In Lisp , for example, every proper list ends with a link to a special node, denoted by nil or () . The advantages of the fancy variants are often limited to
1755-469: Is the maximum possible size without relocating data. A fixed-size array will suffice in applications where the maximum logical size is fixed (e.g. by specification), or can be calculated before the array is allocated. A dynamic array might be preferred if: To avoid incurring the cost of resizing many times, dynamic arrays resize by a large amount, such as doubling in size, and use the reserved space for future expansion. The operation of adding an element to
1820-483: Is to unlink themselves from these lists. In a 'multiply linked list', each node contains two or more link fields, each field being used to connect the same set of data arranged in a different order (e.g., by name, by department, by date of birth, etc.). While a doubly linked list can be seen as a special case of multiply linked list, the fact that the two and more orders are opposite to each other leads to simpler and more efficient algorithms, so they are usually treated as
1885-549: The Java API and the .NET Framework . The generic List<> class supplied with version 2.0 of the .NET Framework is also implemented with dynamic arrays. Smalltalk 's OrderedCollection is a dynamic array with dynamic start and end-index, making the removal of the first element also O(1). Python 's list datatype implementation is a dynamic array the growth pattern of which is: 0, 4, 8, 16, 24, 32, 40, 52, 64, 76, ... Delphi and D implement dynamic arrays at
1950-1035: The MIT Lincoln Laboratory published a review article entitled "Computer languages for symbol manipulation" in IRE Transactions on Human Factors in Electronics in March 1961 which summarized the advantages of the linked list approach. A later review article, "A Comparison of list-processing computer languages" by Bobrow and Raphael, appeared in Communications of the ACM in April 1964. Several operating systems developed by Technical Systems Consultants (originally of West Lafayette Indiana, and later of Chapel Hill, North Carolina) used singly linked lists as file structures. A directory entry pointed to
2015-525: The golden ratio as well as the value 1.5. Many textbooks, however, use a = 2 for simplicity and analysis purposes. Below are growth factors used by several popular implementations: The dynamic array has performance similar to an array, with the addition of new operations to add and remove elements: Dynamic arrays benefit from many of the advantages of arrays, including good locality of reference and data cache utilization, compactness (low memory use), and random access . They usually have only
Dynamic array - Misplaced Pages Continue
2080-443: The n th person is reached, one should remove them from the circle and have the members close the circle. The process is repeated until only one person is left. That person wins the election. This shows the strengths and weaknesses of a linked list vs. a dynamic array, because if the people are viewed as connected nodes in a circular linked list, then it shows how easily the linked list is able to delete nodes (as it only has to rearrange
2145-441: The 'data', 'information', 'value', 'cargo', or 'payload' fields. The 'head' of a list is its first node. The 'tail' of a list may refer either to the rest of the list after the head, or to the last node in the list. In Lisp and some derived languages, the next node may be called the ' cdr ' (pronounced /'kʊd.əɹ/ ) of the list, while the payload of the head node may be called the 'car'. Singly linked lists contain nodes which have
2210-586: The 'previous' node in the sequence. The two links may be called 'forward('s') and 'backwards', or 'next' and 'prev'('previous'). A technique known as XOR-linking allows a doubly linked list to be implemented using a single link field in each node. However, this technique requires the ability to do bit operations on addresses, and therefore may not be available in some high-level languages. Many modern operating systems use doubly linked lists to maintain references to active processes, threads, and other dynamic objects. A common strategy for rootkits to evade detection
2275-692: The Logic Theory Machine" by Newell and Shaw in Proc. WJCC, February 1957. Newell and Simon were recognized with the ACM Turing Award in 1975 for having "made basic contributions to artificial intelligence, the psychology of human cognition, and list processing". The problem of machine translation for natural language processing led Victor Yngve at Massachusetts Institute of Technology (MIT) to use linked lists as data structures in his COMIT programming language for computer research in
2340-727: The Logic Theory Machine, the General Problem Solver , and a computer chess program. Reports on their work appeared in IRE Transactions on Information Theory in 1956, and several conference proceedings from 1957 to 1959, including Proceedings of the Western Joint Computer Conference in 1957 and 1958, and Information Processing (Proceedings of the first UNESCO International Conference on Information Processing) in 1959. The now-classic diagram consisting of blocks representing list nodes with arrows pointing to successive list nodes appears in "Programming
2405-496: The System 360/370 machines, used a double linked list for their file system catalog. The directory structure was similar to Unix, where a directory could contain files and other directories and extend to any depth. Each record of a linked list is often called an 'element' or ' node '. The field of each node that contains the address of the next node is usually called the 'next link' or 'next pointer'. The remaining fields are known as
2470-479: The actual data referenced, which extends off the end of the referencing record. A good example that highlights the pros and cons of using dynamic arrays vs. linked lists is by implementing a program that resolves the Josephus problem . The Josephus problem is an election method that works by having a group of people stand in a circle. Starting at a predetermined person, one may count around the circle n times. Once
2535-409: The addresses of the last node of each piece. The operation consists in swapping the contents of the link fields of those two nodes. Applying the same operation to any two nodes in two distinct lists joins the two list into one. This property greatly simplifies some algorithms and data structures, such as the quad-edge and face-edge . The simplest representation for an empty circular list (when such
2600-549: The array sequentially will actually involve accessing multiple non-contiguous areas of memory, so the many advantages of the cache-friendliness of this data structure are lost. Compared to linked lists , dynamic arrays have faster indexing (constant time versus linear time) and typically faster iteration due to improved locality of reference; however, dynamic arrays require linear time to insert or delete at an arbitrary location, since all following elements must be moved, while linked lists can do this in constant time. This disadvantage
2665-408: The array. Naïve resizable arrays are the simplest way of implementing a resizable array in C. They don't waste any memory, but appending to the end of the array always takes Θ( n ) time. Linearly growing arrays pre-allocate ("waste") Θ(1) space every time they re-size the array, making them many times faster than naïve resizable arrays -- appending to the end of the array still takes Θ( n ) time but with
Dynamic array - Misplaced Pages Continue
2730-432: The basis. The principal benefit of a linked list over a conventional array is that the list elements can be easily inserted or removed without reallocation or reorganization of the entire structure because the data items do not need to be stored contiguously in memory or on disk, while restructuring an array at run-time is a much more expensive operation. Linked lists allow insertion and removal of nodes at any point in
2795-453: The buffer has not only amortized but worst-case constant time. Bagwell (2002) presented the VList algorithm, which can be adapted to implement a dynamic array. Naïve resizable arrays -- also called "the worst implementation" of resizable arrays -- keep the allocated size of the array exactly big enough for all the data it contains, perhaps by calling realloc for each and every item added to
2860-401: The capacity. This threshold must be strictly smaller than 1/ a in order to provide hysteresis (provide a stable band to avoid repeatedly growing and shrinking) and support mixed sequences of insertions and removals with amortized constant cost. Dynamic arrays are a common example when teaching amortized analysis . The growth factor for the dynamic array depends on several factors including
2925-409: The circle by directly referencing them by their position in the array. The list ranking problem concerns the efficient conversion of a linked list representation into an array. Although trivial for a conventional computer, solving this problem by a parallel algorithm is complicated and has been the subject of much research. A balanced tree has similar memory access patterns and space overhead to
2990-446: The complexity of the algorithms, not in their efficiency. A circular list, in particular, can usually be emulated by a linear list together with two variables that point to the first and last nodes, at no extra cost. Double-linked lists require more space per node (unless one uses XOR-linking ), and their elementary operations are more expensive; but they are often easier to manipulate because they allow fast and easy sequential access to
3055-820: The cost of an insertion due to reallocation would still be amortized O(1). This helps with appending elements at the array's end, but inserting into (or removing from) middle positions still carries prohibitive costs due to data moving to maintain contiguity. An array from which many elements are removed may also have to be resized in order to avoid wasting too much space. On the other hand, dynamic arrays (as well as fixed-size array data structures ) allow constant-time random access , while linked lists allow only sequential access to elements. Singly linked lists, in fact, can be easily traversed in only one direction. This makes linked lists unsuitable for applications where it's useful to look up an element by its index quickly, such as heapsort . Sequential access on arrays and dynamic arrays
3120-470: The dynamic array are stored contiguously at the start of the underlying array, and the remaining positions towards the end of the underlying array are reserved, or unused. Elements can be added at the end of a dynamic array in constant time by using the reserved space, until this space is completely consumed. When all space is consumed, and an additional element is to be added, then the underlying fixed-size array needs to be increased in size. Typically resizing
3185-478: The end and iteration over the list are slower than for a dynamic array, in theory and in practice, due to non-contiguous storage and tree traversal/manipulation overhead. Gap buffers are similar to dynamic arrays but allow efficient insertion and deletion operations clustered near the same arbitrary location. Some deque implementations use array deques , which allow amortized constant time insertion/removal at both ends, instead of just one end. Goodrich presented
3250-415: The end might work as follows: As n elements are inserted, the capacities form a geometric progression . Expanding the array by any constant proportion a ensures that inserting n elements takes O ( n ) time overall, meaning that each insertion takes amortized constant time. Many dynamic arrays also deallocate some of the underlying storage if its size drops below a certain threshold, such as 30% of
3315-563: The field of linguistics . A report on this language entitled "A programming language for mechanical translation" appeared in Mechanical Translation in 1958. Another early appearance of linked lists was by Hans Peter Luhn who wrote an internal IBM memorandum in January 1953 that suggested the use of linked lists in chained hash tables. LISP , standing for list processor, was created by John McCarthy in 1958 while he
SECTION 50
#17327824866733380-538: The first node (i.e., the "next link" pointer of the last node has the memory address of the first node). In the case of a circular doubly linked list, the first node also points to the last node of the list. In some implementations an extra 'sentinel' or 'dummy' node may be added before the first data record or after the last one. This convention simplifies and accelerates some list-handling algorithms, by ensuring that all links can be safely dereferenced and that every list (even one that contains no data elements) always has
3445-593: The first sector of a file, and succeeding portions of the file were located by traversing pointers. Systems using this technique included Flex (for the Motorola 6800 CPU), mini-Flex (same CPU), and Flex9 (for the Motorola 6809 CPU). A variant developed by TSC for and marketed by Smoke Signal Broadcasting in California, used doubly linked lists in the same manner. The TSS/360 operating system, developed by IBM for
3510-581: The language's core. Ada 's Ada.Containers.Vectors generic package provides dynamic array implementation for a given subtype. Many scripting languages such as Perl and Ruby offer dynamic arrays as a built-in primitive data type . Several cross-platform frameworks provide dynamic array implementations for C , including CFArray and CFMutableArray in Core Foundation , and GArray and GPtrArray in GLib . Common Lisp provides
3575-417: The links to the different nodes). However, the linked list will be poor at finding the next person to remove and will need to search through the list until it finds that person. A dynamic array, on the other hand, will be poor at deleting nodes (or elements) as it cannot remove one node without individually shifting all the elements up the list by one. However, it is exceptionally easy to find the n th person in
3640-419: The list in both directions. In a doubly linked list, one can insert or delete a node in a constant number of operations given only that node's address. To do the same in a singly linked list, one must have the address of the pointer to that node, which is either the handle for the whole list (in case of the first node) or the link field in the previous node. Some algorithms require access in both directions. On
3705-422: The list, and allow doing so with a constant number of operations by keeping the link previous to the link being added or removed in memory during list traversal. On the other hand, since simple linked lists by themselves do not allow random access to the data or any form of efficient indexing, many basic operations—such as obtaining the last node of the list, finding a node that contains a given datum, or locating
3770-422: The next output node does not need special handling for empty lists. However, sentinel nodes use up extra space (especially in applications that use many short lists), and they may complicate other operations (such as the creation of a new empty list). However, if the circular list is used merely to simulate a linear list, one may avoid some of this complexity by adding a single sentinel node to every list, between
3835-482: The other hand, doubly linked lists do not allow tail-sharing and cannot be used as persistent data structures . A circularly linked list may be a natural option to represent arrays that are naturally circular, e.g. the corners of a polygon , a pool of buffers that are used and released in FIFO ("first in, first out") order, or a set of processes that should be time-shared in round-robin order . In these applications,
3900-411: The performance of iteration. Moreover, arbitrarily many elements may be inserted into a linked list, limited only by the total memory available; while a dynamic array will eventually fill up its underlying array data structure and will have to reallocate—an expensive operation, one that may not even be possible if memory is fragmented, although the cost of reallocation can be averaged over insertions, and
3965-445: The place where a new node should be inserted—may require iterating through most or all of the list elements. Linked lists were developed in 1955–1956, by Allen Newell , Cliff Shaw and Herbert A. Simon at RAND Corporation and Carnegie Mellon University as the primary data structure for their Information Processing Language (IPL). IPL was used by the authors to develop several early artificial intelligence programs, including
SECTION 60
#17327824866734030-418: The procedures generally need extra arguments and more complicated base cases. Linear singly linked lists also allow tail-sharing , the use of a common final portion of sub-list as the terminal portion of two different lists. In particular, if a new node is added at the beginning of a list, the former list remains available as the tail of the new one—a simple example of a persistent data structure . Again, this
4095-456: The sequence during iteration. More complex variants add additional links, allowing more efficient insertion or removal of nodes at arbitrary positions. A drawback of linked lists is that data access time is linear in respect to the number of nodes in the list. Because nodes are serially linked, accessing any node requires that the prior node be accessed beforehand (which introduces difficulties in pipelining ). Faster access, such as random access,
4160-591: The size of the data. In contrast, a dynamic array requires only the space for the data itself (and a very small amount of control data). It can also be slow, and with a naïve allocator, wasteful, to allocate memory separately for each new element, a problem generally solved using memory pools . Some hybrid solutions try to combine the advantages of the two representations. Unrolled linked lists store several elements in each list node, increasing cache performance while decreasing memory overhead for references. CDR coding does both these as well, by replacing references with
4225-478: Was at MIT and in 1960 he published its design in a paper in the Communications of the ACM , entitled "Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I". One of LISP's major data structures is the linked list. By the early 1960s, the utility of both linked lists and languages which use these structures as their primary data representation was well established. Bert Green of
#672327