Linked List
Linked List
A linked list whose nodes contain two fields: an integer value and a link to the next node. The
last node is linked to a terminator used to signify the end of the list.
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 (the abstract data
type), stacks, queues, associative arrays, and S-expressions, though it is not uncommon to
implement the other data structures directly without using a list as the basis of implementation.
The principal benefit of a linked list over a conventional array is that the list elements can easily
be inserted or removed without reallocation or reorganization of the entire structure because the
data items need not be stored contiguously in memory or on disk, while an array has to be
declared in the source code, before compiling and running the program. Linked lists allow
insertion and removal of nodes at any point in the list, and can do so with a constant number of
operations if the link previous to the link being added or removed is maintained during list
traversal.
On the other hand, simple linked lists by themselves do not allow random access to the data, or
any form of efficient indexing. Thus, many basic operations such as obtaining the last node of
the list (assuming that the last node is not maintained as separate node reference in the list
structure), or finding a node that contains a given datum, or locating the place where a new node
should be inserted may require sequential scanning of most or all of the list elements. The
advantages and disadvantages of using linked lists are as follows:-
Advantages:
Linked lists are a dynamic data structure, allocating the needed memory while the program is
running.
Insertion and deletion node operations are easily implemented in a linked list.
Linear data structures such as stacks and queues are easily executed with a linked list.
They can reduce access time and may expand in real time without memory overhead.
Disadvantages:
They have a tendency to waste memory due to pointers requiring extra storage space.
Nodes in a linked list must be read in order from the beginning as linked lists are
inherently sequential access.
Nodes are stored incontiguously, greatly increasing the time required to access individual
elements within the list.
Difficulties arise in linked lists when it comes to reverse traversing. Singly linked lists are
extremely difficult to navigate backwards, and while doubly linked lists are somewhat easier
to read, memory is wasted in allocating space for a back pointer.
Linked Lists
Introduction
One disadvantage of using arrays to store data is that arrays are static structures and therefore
cannot be easily extended or reduced to fit the data set. Arrays are also expensive to maintain
new insertions and deletions. In this chapter we consider another data structure called Linked
Lists that addresses some of the limitations of arrays.
A linked list is a linear data structure where each element is a separate object.
Each element (we will call it a node) of a list is comprising of two items - the data and a
reference to the next node. The last node has a reference to null. The entry point into a linked list
is called the head of the list. It should be noted that head is not a separate node, but the reference
to the first node. If the list is empty then the head is a null reference.
A linked list is a dynamic data structure. The number of nodes in a list is not fixed and can grow
and shrink on demand. Any application which has to deal with an unknown number of objects
will need to use a linked list.
One disadvantage of a linked list against an array is that it does not allow direct access to the
individual elements. If you want to access a particular item then you have to start at the head and
follow the references until you get to that item.
Another disadvantage is that a linked list uses more memory compare with an array - we extra 4
bytes (on 32-bit CPU) to store a reference to the next node.
Another important type of a linked list is called a circular linked list where last node of the list
points back to the first node (or the head) of the list.
This article includes a list of references, but its sources remain unclear
because it has insufficient inline citations. Please help to improve this
article byintroducing more precise citations. (September 2009)
reveals previously concealed items or results in an empty stack, but, if the stack is empty, it goes
into underflow state, which means no items are present in stack to be removed.
A stack is a restricted data structure, because only a small number of operations are performed
on it. The nature of the pop and push operations also means that stack elements have a natural
order. Elements are removed from the stack in the reverse order to the order of their addition.
Therefore, the lower elements are those that have been on the stack the longest.[2]
Contents
[hide]
1 History
2 Abstract definition
3 Inessential operations
4 Software stacks
o
4.1 Implementation
4.1.1 Array
5 Hardware stacks
o
6 Applications
o
6.2 Backtracking
7 Security
8 See also
9 References
10 Further reading
11 External links
History[edit]
The stack was first proposed in 1946, in the computer design of Alan M. Turing (who used the
terms "bury" and "unbury") as a means of calling and returning from subroutines.[clarification
needed]
Munich proposed the idea in 1955 and filed a patent in 1957.[3] The same concept was
developed, independently, by the Australian Charles Leonard Hamblin in the first half of 1957.[4]
Abstract definition[edit]
A stack is a basic computer science data structure and can be defined in an abstract,
implementation-free manner, or it can be generally defined as a linear list of items in which all
additions and deletion are restricted to one end that is Top.
This is a VDM (Vienna Development Method) description of a stack:[5]
Function signatures:
init: -> Stack
push: N x Stack -> Stack
top: Stack -> (N U ERROR)
pop: Stack -> Stack
isempty: Stack -> Boolean
(where N indicates an element (natural numbers in this case), and U indicates set union)
Semantics:
top(init()) = ERROR
top(push(i,s)) = i
pop(init()) = init()
pop(push(i, s)) = s
isempty(init()) = true
Inessential operations[edit]
In many implementations, a stack has more operations than "push" and "pop". An example is
"top of stack", or "peek", which observes the top-most element without removing it from the
stack.[6] Since this can be done with a "pop" and a "push" with the same data, it is not essential.
An underflow condition can occur in the "stack top" operation if the stack is empty, the same as
"pop". Also, implementations often have a function which just returns whether the stack is
empty.
Software stacks[edit]
Implementation[edit]
In most high level languages, a stack can be easily implemented either through an array or
a linked list. What identifies the data structure as a stack in either case is not the implementation
but the interface: the user is only allowed to pop or push items onto the array or linked list, with
few other helper operations. The following will demonstrate both implementations, using C.
Array[edit]
The array implementation aims to create an array where the first element (usually at the zerooffset) is the bottom. That is, array[0] is the first element pushed onto the stack and the last
element popped off. The program must keep track of the size, or the length of the stack. The
stack itself can therefore be effectively implemented as a two-element structure in C:
typedef struct {
size_t size;
int items[STACKSIZE];
} STACK;
The push() operation is used both to initialize the stack, and to store values to it. It is responsible
for inserting (copying) the value into the ps->items[] array and for incrementing the element
Unlike the array implementation, our structure typedef corresponds not to the entire stack
structure, but to a single node:
typedef struct stack {
int data;
struct stack *next;
} STACK;
Such a node is identical to a typical singly linked list node, at least to those that are implemented
in C.
The push() operation both initializes an empty stack, and adds a new node to a non-empty one.
It works by receiving a data value to push onto the stack, along with a target stack, creating a
new node by allocating memory for it, and then inserting it into a linked list as the new head:
void push(STACK **head, int value)
{
STACK *node = malloc(sizeof(STACK)); /* create a new node */
if (node == NULL){
fputs("Error: no space available for node\n", stderr);
abort();
} else {
/* initialize node */
node->data = value;
node->next = empty(*head) ? NULL : *head; /* insert new head if any */
*head = node;
}
}
A pop() operation removes the head from the linked list, and assigns the pointer to the head to
the previous second node. It checks whether the list is empty before popping from it:
int pop(STACK **head)
{
if (empty(*head)) {
/* stack is empty */
//pop a node
Tree structure
From Wikipedia, the free encyclopedia
The original Encyclopdie used a tree diagram to show the way in which its subjects were
ordered.
A tree structure is conceptual, and appears in several forms. For a discussion of tree structures in
specific fields, see Tree (data structure) for computer science: insofar as it relates to graph
theory, see tree (graph theory), or also tree (set theory). Other related pages are listed below.
Contents
[hide]
3 Representing trees
o
4 See also
5 References
6 Further reading
7 External links
Terminology and properties[edit]
The tree elements are called "nodes". The lines connecting elements are called "branches".
Nodes without children are called leaf nodes, "end-nodes", or "leaves".
Every finite tree structure has a member that has no superior. This member is called the "root"
or root node. The root is the starting node. But the converse is not true: infinite tree structures
may or may not have a root node.
The names of relationships between nodes are modeled after family relations. The gender-neutral
names "parent" and "child" have largely displaced the older "father" and "son" terminology,
although the term "uncle" is still used for other nodes at the same level as the parent.
A node's "parent" is a node one step higher in the hierarchy (i.e. closer to the root node) and
lying on the same branch.
A node that is connected to all lower-level nodes is called an "ancestor". The connected
lower-level nodes are "descendants" of the ancestor node.
In the example, "encyclopedia" is the parent of "science" and "culture", its children. "Art" and
"craft" are siblings, and children of "culture", which is their parent and thus one of their
ancestors. Also, "encyclopedia", being the root of the tree, is the ancestor of "science", "culture",
"art" and "craft". Finally, "science", "art" and "craft", being leaves, are ancestors of no other
node.
Tree structures are used to depict all kinds of taxonomic knowledge, such as family trees, the
biological evolutionary tree, the evolutionary tree of a language family, the grammatical
structure of a language (a key example being S NP VP, meaning a sentence is a noun phrase
and a verb phrase, with each in turn having other components which have other components), the
way web pages are logically ordered in a web site, mathematical trees of integer sets, et cetera.
In a tree structure there is one and only one path from any point to any other point.
Tree structures are used extensively in computer science (see Tree (data
structure) and telecommunications.)
For a formal definition see set theory, and for a generalization in which children are not
necessarily successors, see prefix order.
Examples of tree structures[edit]
Internet:
usenet hierarchy
Information management: Dewey Decimal System, PSH, this hierarchical bulleted list
Computer Science:
Red-Black Tree
AVL tree
R-tree
Node Representations
Usually the first step in representing a graph is to map the nodes to a set of contiguous integers.
(0,|V|-1) is the most convenient in C programs - other, more flexible, languages allow you
greater choice! The mapping can be performed using any type of search structure: binary
trees, m-way trees, hash tables, etc.
Adjacency Matrix
Having mapped the vertices to integers, one simple representation for the graph uses
an adjacency matrix. Using a |V| x |V| matrix of booleans, we set aij = true if an edge
connects i and j. Edges can be undirected, in which case if aij = true, then aji = true also,
or directed, in which aij != aji, unless there are two edges, one in either direction,
between i and j. The diagonal elements, aii, may be either ignored or, in cases such as state
machines, where the presence or absence of a connection from a node to itself is relevant, set
to true or false as required.
When space is a problem, bit maps can be used for the adjacency matrix. In this case, an ADT
for the adjacency matrix improves the clarity of your code immensely by hiding the bit twiddling
that this space saving requires! In undirected graphs, only one half of the matrix needs to be
stored, but you will need to calculate the element addresses explicitly yourself. Again an ADT
can hide this complexity from a user! If the graph is dense, iemost of the nodes are connected by
edges, then the O(|V|2) cost of initialising an adjacency matrix is matched by the cost of
inputting and setting the edges. However, if the graph is sparse, ie |E| is closer to |V|, then an
adjacency list representation may be more efficient.
Adjacency List Representation
Adjacency lists are lists of nodes that are connected to a given node. For each node, a linked list
of nodes connected to it can be set up. Adding an edge to a graph will generate two entries in
adjacency lists - one in the lists for each of its extremities.
Traversing a graph
Depth-first Traversal
A depth-first traverse of a graph uses an additional array to flag nodes that it has visited already.
Using the adjacency matrix structure:
struct t_graph {
int n_nodes;
graph_node *nodes;
int *visited;
adj_matrix am;
}
ListHead,
ListItem,
ListNext
ANodeIndex
method.
The complexity of this traversal can be readily seen to be O(|V|+|E|), because it sets visited for
each node and then visits each edge twice (each edge appears in two adjacency lists).
Breadth-first Traversal
To scan a graph breadth-first, we use a FIFO queue.
static queue q;
void search( graph g ) {
q = ConsQueue( g->n_nodes );
for(k=0;k<g->n_nodes;k++) g->visited[k] = 0;
search_index = 0;
for(k=0;k<g->n_nodes;k++) {
if ( !g->visited[k] ) visit( g, k );
}
Matrix Representation
Matrix Rep Matrix Rep. Same basics as introduced already Same basics as introduced already.
Convenient method of working with vectors.
Superposition Complete set of vectors can be used to
express any other vector.
Complete set of N vectors can form other complete sets of N vectors.
Can find set of vectors for Hermitian operator satisfying Can find set of vectors for Hermitian
operator satisfying
Eigenvectors and eigenvalues