0% found this document useful (0 votes)
6 views41 pages

2023(Fall)_DS - 04. Linked Lists

The document provides an overview of data structures, focusing on linked lists, including singly linked lists and their operations such as insertion and deletion. It also discusses circular lists, sparse matrices, and double linked lists, detailing their structures and manipulation methods. Additionally, it touches on the use of iterators for visiting elements in containers.

Uploaded by

buz9413
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views41 pages

2023(Fall)_DS - 04. Linked Lists

The document provides an overview of data structures, focusing on linked lists, including singly linked lists and their operations such as insertion and deletion. It also discusses circular lists, sparse matrices, and double linked lists, detailing their structures and manipulation methods. Additionally, it touches on the use of iterators for visiting elements in containers.

Uploaded by

buz9413
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 41

Data Structures

資料結構

Linked Lists

Department of Computer Science


National Tsing Hua University
Array Recap
• Store an ordered list using sequential mapping
– Element (node) ai is stored in the location Li of the array
– Next node is at the location Li+1
• Pros:
– Suitable for random access
– Efficient to insert/delete from the end
– Adequate for special data structures, Stack and Queue.
• Con:
– Difficult to insert/delete nodes at arbitrary location

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 …

Data field Link field

3
Chain
SLL Operation: Insert
first

BAT CAT EAT FAT …

a GAT

• Steps to do when we want to insert a ”GAT” in


between “CAT” and “EAT” nodes
– Create a new node “a” and set data field to “GAT”
– Set the link field of “a” to “EAT” node
– Set the link field of “CAT” node to “a”

4 You do not need to move or shift any nodes!


SLL Operation: Delete
first

BAT CAT EAT FAT …

• Steps to do when we want to delete a ”EAT”


node from the list
– Locate the node “a” precedes the “EAT” node
– Set the link field of “a” to node next to “EAT” node
– Delete the “EAT” node

5 You do not need to move or shift any nodes!


Conceptual Design
• Defining a “ChainNode” class
– Data field
– Link field
• Designing a “Chain” class
– Support various operation on ChainNodes

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();

// Insert a node with data=50


void Insert50(ChainNode *x);

// 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);

// Create and set the fields of 1st node


first = new ChainNode(10,second);
}

first 10 20 0

11
Chain Operations

void Chain::Insert50(ChainNode *x)


{
if(first) // Insert after x
xlink = new ChainNode(50, x->link);
else // Insert into empty list
first = new ChainNode(50);
}
x
first 10 20 … 45 3 …

50

12
Chain Operations

void Chain::Delete(ChainNode *x, ChainNode *y)


{ // x is the node to be deleted and y is the node
// preceding x
if(x==first) first = first->link;
else y->link = x->link;
delete x; x=NULL;
}
x
first 10 20 … 45 3 …

13
Template Chain Class
Template < class T > class Chain; // Forward declaration

template < class T >


class ChainNode {
friend class Chain <T>;
private:
T data;
ChainNode<T>* link;
};

template <class T>


class Chain {
public:
// Constructor
Chain(void) {first = last = NULL;}

// 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);
}

template < class T >


void Chain<T>::Concatenate(Chain<T>& b)
{ // b is concatenated to the end of *this
if ( first ) { last->link = b.first; last = b.last; }
else { first = b.first; last = b.last; }
b. first = b.last = 0;
}

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

• Check for the last node


– if(current->link == first)
• You could visit a node from any position
18
Circular Lists : Insert
• Suppose we want to insert a new node at the
front of list
• Set link field of new node to first and set first
to new node
• Go to the last node and set the link field to
new node
first first
xnew 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);

if(last){ // nonempty list


newNode->link = last->link;
last->link = newNode;
}
else{ // empty list
last = newNode;
newNode->link = newNode;
}
}

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

x->left->right = x->right; x->right->left = x->left;


first
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;
}

• In a linked list representation


for (ChainNode<int> *ptr=first; ptr!=0; ptr=ptr->link)
{
int currentItem = ptr->data;
// 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;
}

• An iterator is a pointer to an element in a container.


• Using dereferencing operator (*) to access an element
• Support pre- or post- increment operator (++)
37
C++ Iterators
• Input iterator
– Read access, pre- and post- “++” operators.
• Output iterator
– Write access, pre- and post- “++” operators.
• Forward iterator
– pre- and post- “++” operators.
• Bidirectional iterator
– pre- and post- “++” and “--” operators.
• Random access iterator
– Permit pointer jumps by arbitrary amounts.
•38 All iterators supports “==”, “!=” and “*” operators
Forward Iterator for Chain
template <class T>
class Chain {
public:
// Constructor
Chain(void) {first = last = NULL;}

// Chain operations…

class ChainIterator{…};

// Get the first element


ChainIterator begin() {return
ChainIterator(first);}

// Get the end of the list


ChainIterator end() {return ChainIterator(0);}
private:
ChainNode<T> *first;
ChainNode<T> *last;
};
39
Forward Iterator for Chain
• General usage
void main()
{
Chain<int> myChain;
// do operations on myChain here…

// print out every element in myChain


Chain<int>::ChainIterator my_it;
for (my_it = myChain.begin(); myChain!=myChain.end(); ++m_it)
cout << *m_it << endl;

// Use STL algorithm to calculate the sum of myChain


int sum = std::accumulate(myChain.begin(), myChain.end(),0);
}

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 &current->data;}

// Increment operator
ChainIterator& operator++() // pre-”++”
{ current = current->link ; return *this; }

ChainIterator operator++(int)// post- “++”


{
ChainIterator old = *this;
current = current->link;
return old;
}

// Equality operators
bool operator!=(const ChainIterator right) const
{ return current != right.current; }

bool operator==(const ChainIterator right) const


{ return current == right.current;}

private:
ChainNode<T>* current;
41
};

You might also like