2023(Fall)_DS - 04. Linked Lists
2023(Fall)_DS - 04. Linked Lists
資料結構
Linked Lists
2
Linked Representation
• Nodes are no longer continue in the memory
• Each node stores the address or location of
the next one
• Singly Linked List (SLL)
– each node has exactly one pointer field
Node
a0 a1 a2 …
3
Chain
SLL Operation: Insert
first
a GAT
Chain
first BAT CAT EAT FAT …
ChainNode
6
ChainNode & Chain Classes
• Composite class
class ChainNode class Chain
{ {
friend class Chain; public:
public: // Create a chain with two nodes
// Constructor void Create2();
ChainNode(int
value=0, ChainNode* // Insert a node with data=50
next=NULL){ void Insert50(ChainNode *x);
data = value;
link = next; // Delete a node
void Delete(ChainNode *x, ChainNode
private: *y);
int data;
ChainNode *link; private:
}; ChainNode *first;
};
7
ChainNode & Chain Classes
• Nested class
class Chain
{
public:
// Create a chain with two nodes
void Create2();
// Delete a node
void Delete(ChainNode *x, ChainNode
*y);
private:
class ChainNode{
public:
int data;
ChainNode *link;
8 }
ChainNode *first;
Review Pointer Manipulation
• Declaration • Access members
– NodeA *a1=NULL, – a1->memData;
*a2=NULL; – a1->memFunc();
• Allocate memory – (*a1).memData;
– a1 = new NodeA; – (*a1).memFunc();
– a2 = new NodeA[10];
• Delete memory
– delete a1; a1=NULL;
– delete [] a2; a2=NULL;
9
Pointer Assignment
• ChainNode *x, *y; • x = y;
x 10 x 10
y 20 20
y
• *x = *y;
x 20
y 20
10
Chain Operations
void Chain::Create2()
{
// Create and set the fields of 2nd node
ChainNode* second = new ChainNode(20,0);
first 10 20 0
11
Chain Operations
50
12
Chain Operations
13
Template Chain Class
Template < class T > class Chain; // Forward declaration
// Chain operations…
private:
ChainNode<T> *first;
ChainNode<T> *last;
14
};
Chain Operations
template < class T >
void Chain<T>::InsertBack(const T& e)
{
if(first) {// Non-empty chain
last->link = new ChainNode<T>(e);
last = last->link;
}
else // Insert into an empty chain
first = last = new ChainNode<T>(e);
}
15
Chain Operations
• Reverse a chain, such that (a1, …, an) turns
into (an, …, a1).
first 10 20 … 45 3 0
Reverse
first 3 45 20 10 0
16
Chain Operations
template < class T >
void Chain<T>::Reverse(void)
{ // Turn a chain,(a1, …, an) into (an, …, a1)
ChainNode<T> *current = first, *previous = NULL;
while (current) {
ChainNode<T> *r = previous;
previous = current; // r is behind the previous
current = current->link; // move current to next
node
previous->link = r; // link previous to previous
node
}
first = previous;
}
17
Circular Lists
• A singly-linked circular list
• The link field of the last node points to the
first node
first …
x1 x2 xn
19
Circular Lists
• Instead of using a pointer to store the first
node, it is more convenient to store the last
node of a circular list
• We could away access the first node via
last->link
x1 x2 … xn last
20
Circular Lists : Insert at Front
Template<class T>
void CircularList<T>::InsertFront(const T& e)
{
ChainNode<T>* newNode = new ChainNode<T>(e);
21
Sparse Matrix
• A matrix has many zero elements.
• Devise a sequential array
2 0 0 0
– store non-zero elements 4
0 0 3
– row-major order. 0 0 0 0
• Access specific column is difficult!
8 0 0 1
• Using circular lists representation. 0 0 6 0
22
Should be 5, 4, 6
Linked Sparse Matrix
H H0 H1 H2 H3 H4
4 5 6
H0
0 0 2
same header 2 0 0 0
H1 nodes 4 0 0 3
1 0 4 1 3 3
0 0 0 0
H2
8 0 0 1
H3 0 0 6 0
3 0 8 3 3 1
H4
4 2 6
23
Linked Structure
• Each non-zero term represents an element
node that stores
– Data of row, col, and value.
– A down field to link to the next non-zero
term in the same column.
– A right field to link to the next non-zero
term in the same row.
24
Linked Structure
• Each row(or column) is represented as a circular list with a header
node. next
• Each head node has three fields: down right
– Down: link to the 1st non-zero term in the column. Header node
– Right: link to the 1st non-zero term in the row.
row col value
– Next: link to the next head node.
down right
• The header of header nodes (a circular list)
Element node
– Store dimension of the matrix
• The header node of row i is also the header node of column i
• Given a nxm sparse matrix with r non-zero terms, the total number
of required nodes are
Max{n,m} + r + 1
25
struct Triple{int row, col, value;};
class Matrix; // forward declaration
class MatrixNode {
friend class Matrix;
// for reading in a matrix
friend istream& operator>>(istream&, Matrix&);
private:
MatrixNode *down , *right;
bool head; next
union {
MatrixNode *next;
Triple triple;
down right
};
MatrixNode(bool, Triple*); // constructor Header node
}
MatrixNode::MatrixNode(bool b, Triple *t) // constructor
{
head = b; row col value
if (b) {right = down = this;} // row/column header node
}
else triple = *t; // element node or header node of header lists down right
class Matrix{ Element node
friend istream& operator>>(istream&, Matrix&);
public:
~Matrix(); // destructor
private:
MatrixNode *headnode;
};
26
Create a Sparse Matrix
• Input format: The 1st line gives the dimension
of matrix and # of non-zero terms. Each
subsequent input line is a triple of the form (I,
j, aij). Triples are ordered by rows and within
rows by columns.
Input
2 0 0 0 5,4,6;
4 0 0 3 0,0,2;
1,0,4;
0 0 0 0 1,3,3;
3,0,8;
8 0 0 1
3,3,1;
27
0 0 6 0 4,2,6;
Create a Sparse Matrix
• Performance analysis
– Set up header nodes, O(max{n,m})
– Set up non-zero nodes, O(r)
– Close column lists, O(max{n,m})
– Link header nodes, O(max{n,m})
• Total complexity: O(max{n,m}+r) = O(n+m+r)
28
Double Linked Lists
• Each node has TWO link fields
• Could move in TWO directions to visit nodes
Node
Left link field a0 Right link field
first
Linear list 0 x1 x2 … xn 0
first
Circular list x1 x2 … xn
29
Double Linked Lists : Delete
first x
0 x1 x2 x3 … xn 0
delete x;
first
0 x1 x3 … xn 0
30
Double Linked Lists : Insert
first x
0 x1 x2 x3 … xn 0
p
xnew
p->left = x; p->right=x->right
first x
0 x1 x2 x3 … xn 0
p
xnew
31
x->right->left = p; x->right = p;
Self-Study Topics
• Polynomial using linked lists
• Linked Stacks and Queues
32
Visit Elements in a Container
• Suppose we have a chain C of datatype
Chain<int>.
– Output all integers in C
– Obtain the maximum, minimum or mean of all
integers in C
– Obtain the sum, product, or sum of squares of all
integers in C
• All operations require to visit every element in
the chain C!
33
How to Visit a Container?
For each item in C
{
currentItem = current item in C;
do something with currentItem;
}
• In an array representation
for (int i = 0; i < n; i++)
{
int currentItem = a[i];
// do something with currentItem;
}
34
How to Visit a Container?
For each item in C
{
currentItem = current item in C;
do something with currentItem;
}
35
Visiting a Container using Iterator
• A powerful mechanism to visit a container
with arbitrary data type.
• Guarantee runtime range safety.
• Applicable to all STL algorithms.
• Suitable for team development.
• Might scarify some amount of performance.
// Possible implementation of STL copy algorithm
template < class Iterator >
void copy(Iterator start, Iterator end, Iterator to)
{ // copy from src[start, end) to dst[to, to+end-start)
• while (start != end)
{ *to = *start ; start++ ; to++; }
} 36
What is an Iterator ?
void main()
{
int x [3] = {0,1,2};
for (int* y = x; y != x+3; y++)
cout << *y << endl;
}
void main()
{
for (Iterator y = start; y != end; y++)
cout << *y << endl;
}
// Chain operations…
class ChainIterator{…};
40
Class ChainIterator{ // A nested class within Chain
public:
// Constructor
ChainIterator(ChainNode<T>* startNode = 0)
{current = startNode;}
// Dereferencing operator
T& operator*() const {return current->data;}
T* operator->() const {return ¤t->data;}
// Increment operator
ChainIterator& operator++() // pre-”++”
{ current = current->link ; return *this; }
// Equality operators
bool operator!=(const ChainIterator right) const
{ return current != right.current; }
private:
ChainNode<T>* current;
41
};