0% found this document useful (0 votes)
0 views

Lecture 4.1

The document provides an overview of Lists as an Abstract Data Type (ADT) and discusses both array-based and linked list implementations. It covers basic operations such as insertion, deletion, and traversal, along with the design of a List class in C++. Additionally, it highlights the advantages of linked lists over array-based lists, particularly in terms of dynamic memory allocation and efficiency for frequent modifications.

Uploaded by

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

Lecture 4.1

The document provides an overview of Lists as an Abstract Data Type (ADT) and discusses both array-based and linked list implementations. It covers basic operations such as insertion, deletion, and traversal, along with the design of a List class in C++. Additionally, it highlights the advantages of linked lists over array-based lists, particularly in terms of dynamic memory allocation and efficiency for frequent modifications.

Uploaded by

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

University of Management &

Technology
Data Structures

List ADT & Linked Lists

Mr. Shoaib Khan


[email protected]

Lecture No. 4.1


Roadmap
 List as an ADT
 An Array-Based Implementation of Lists

 Introduction to Linked Lists


 A Pointer-Based Implementation in C++
 Variations of Linked-lists
Consider Every Day Lists
 Groceries to be purchased
 Job to-do list
 List of assignments for a course

 Can you name some others??


Properties of Lists
 Can have a single element
 Can have no elements
 There can be lists of lists

 We will look at the list as an abstract data type


 Homogeneous
 Finite
length
 Sequential elements
Basic Operations
 Construct an empty list
 Determine whether or not empty
 Insert an element into the list
 Delete an element from the list
 Traverse (iterate through) the list to
 Modify
 Output
 Search for a specific value
 Copy or save
 Rearrange
Designing a List Class

 Should contain at least the following function members


 Constructor
 isEmpty()
 insert()
 delete()
 display()
 Implementation involves
 Defining data members
 Defining function members from design phase
Array-Based Implementation of Lists

 An array is a viable choice for storing list elements


 Elements are sequential
 It is a commonly available data type
 Algorithm development is easy
 Normally sequential orderings of list elements match with
array elements
Implementing Operations
 Constructor
 Static array allocated at compile time
 isEmpty
 Check if size == 0
 Traverse
 Use a loop from 0th element to size – 1
 Insert
 Shift elements to
right of insertion point Also
Alsoadjust
adjust
 Delete sizeup
size upor
or
down
down
 Shift elements back
List Class with Static Array - Problems

 Stuck with "one size fits all"


 Could be wasting space
 Could run out of space

 Better to have instantiation of specific list specify


what the capacity should be
 Thus we consider creating a List class with
dynamically-allocated array
Dynamic-Allocation for List Class
 Changes required in data members
 Eliminate const declaration for CAPACITY
 Add variable data member to store capacity specified by client
program

 Little or no changes required for


 isEmpty()
 display()
 erase()
 insert()
Dynamic-Allocation for List Class
 Now possible to specify different sized lists
cin >> maxListSize;
List aList1 (maxListSize);
List aList2 (500);
Improvements to our List Class
 Problem 1: Array used has fixed capacity
Solution:
 If larger array needed during program execution
 Allocate, copy smaller array to the new one

 Problem 2: Class bound to one type at a time


Solution:
 Create multiple List classes with differing names
 Use class template
Inefficiency of Array-Implemented List

 Insert(), erase() functions inefficient for dynamic lists


 Those that change frequently
 Those with many insertions and deletions

So …
We look for an alternative implementation.
Linked List
For the array-based implementation:
1. First element is at location 0
2. Successor of item at location i is at location i + 1
3. End is at location size – 1

Fix:
1. Remove requirement that list elements be stored in consecutive
location.
2. But then need a "link" that connects each element to its
successor

Linked
LinkedLists
Lists!!!!
Linked List
 Linked list nodes contain
 Data part – stores an element of the list
 Next part – stores link/pointer to next element
(when no next element, null value)
Implementation Overview
A Simple Linked List Class
 We use two classes: Node and List
 Declare Node class for the nodes
 data: double-type data in this example
 next: a pointer to the next node in the list

class Node {
public:
double data; // data
Node* next; // pointer to next
};
A Simple Linked List Class
 Declare List, which contains
 head: a pointer to the first node in the list.
Since the list is empty initially, head is set to NULL

class List {
public:
List(void) { head = NULL; } // constructor
~List(void); // destructor

bool IsEmpty() { return head == NULL; }


Node* InsertNode(int index, double x);
int FindNode(double x);
int DeleteNode(double x);
void DisplayList(void);
private:
Node* head;
};
A Simple Linked List Class
 Operations of List
 IsEmpty: determine whether or not the list is empty
 InsertNode: insert a new node at a particular
position
 FindNode: find a node with a given value
 DeleteNode: delete a node with a given value
 DisplayList: print all the nodes in the list
Inserting a new node
 Node* InsertNode(int index, double x)
 Insert a node with data equal to x after the index’th elements.
 If the insertion is successful, return the inserted node. Otherwise, return NULL.
(If index is < 0 or > length of the list, the insertion will fail.)

 Steps
1. Locate index’th element
2. Allocate memory for the new node
3. Point the new node to its successor
4. Point the new node’s predecessor to the new node
Insertion after the last element

A0 A1 A2

first last

At any point, we can add a new last item x by doing this:

last->next = new ListNode();


last = last->next;
last->data = x;
last->next = null;
A0 A1 A2

first last

At any point, we can add a new last item x by doing this:

last->next = new ListNode() ;


last = last->next;
last->data = x;
last->next = null;
A0 A1 A2

first last

At any point, we can add a new last item x by doing this:

last->next = new ListNode();


last = last->next;
last->data = x;
last->next = null;
A0 A1 A2 x

first last

At any point, we can add a new last item x by doing this:

last->next = new ListNode();


last = last->next;
last->data = x;
last->next = null;
A0 A1 A2 x

first last

At any point, we can add a new last item x by doing this:

last->next = new ListNode();


last = last->next;
last->data = x;
last->next = null;
Insertion at the middle
A0 A1 A2

first current

At any point, we can add a new item x by doing this:

tmp = new ListNode();


tmp->element = x;
tmp->next = current->next;
Current->next = tmp;
A0 A1 A2

first current

tmp

At any point, we can add a new last item x by doing this:

tmp = new ListNode();


tmp->element = x;
tmp->next = current->next;
Current->next = tmp;
A0 A1 A2

first current x

tmp

At any point, we can add a new item x by doing this:

tmp = new ListNode();


tmp->element = x;
tmp->next = current->next;
current->next = tmp;
A0 A1 A2

first current x

tmp

At any point, we can add a new last item x by doing this:

tmp = new ListNode();


tmp->element = x;
tmp->next = current->next;
current->next = tmp;
A0 A1 A2

first current x

tmp

At any point, we can add a new last item x by doing this:

tmp = new ListNode();


tmp->element = x;
tmp->next = current->next;
current->next = tmp;
Inserting a new node
 Possible cases of InsertNode
1. Insert into an empty list
2. Insert in front
3. Insert at back
4. Insert in middle

 But, in fact, only need to handle two cases


 Insert as the first node (Case 1 and Case 2)
 Insert in the middle or at the end of the list (Case 3 and Case 4)
Try to locate index’th
Node* List::InsertNode(int index, double x) {
node. If it doesn’t
if (index < 0) return NULL; exist, return NULL.

int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;

Node* newNode =new Node;


newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;

int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;

Node* newNode =new Node;


newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
} Create a new node
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;

int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;

Node* newNode =new Node;


newNode->data = x;
if (index == 0) { Insert as first element
newNode->next = head; head
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode; newNode
}
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;

int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;

Node* newNode =new Node;


newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode; Insert after currNode
}
currNode
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
newNode
Finding a node
 int FindNode(double x)
 Search for a node with the value equal to x in the list.
 If such a node is found, return its position. Otherwise, return
0.

int List::FindNode(double x) {
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
currNode = currNode->next;
currIndex++;
}
if (currNode) return currIndex;
return 0;
}
Deleting a node

A0 A1 A2

current

current->next = current->next->next;
Deleting a node

A0 A1 A2

current

Current->next = current->next->next; Memory leak!


Deleting a node

A0 A1 A2

current

Node *deletedNode = current->next;


current->next = current->next->next;
delete deletedNode;
Deleting a node
 int DeleteNode(double x)
 Delete a node with the value equal to x from the list.
 If such a node is found, return its position. Otherwise, return 0

.
 Steps
 Find the desirable node (similar to FindNode)
 Release the memory occupied by the found node
 Set the pointer of the predecessor of the found node to the
successor of the found node

 Like InsertNode, there are two special cases


 Delete first node
 Delete the node in middle or at the end of the list
Try to find the node with its
int List::DeleteNode(double x) { value equal to x
Node* prevNode = NULL;
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++;
}
if (currNode) {
if (prevNode) {
prevNode->next = currNode->next;
delete currNode;
}
else {
head = currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
int List::DeleteNode(double x) {
Node* prevNode = NULL;
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++; prevNode currNode
}
if (currNode) {
if (prevNode) {
prevNode->next = currNode->next;
delete currNode;
}
else {
head = currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
int List::DeleteNode(double x) {
Node* prevNode = NULL;
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++;
}
if (currNode) {
if (prevNode) {
prevNode->next = currNode->next;
delete currNode;
}
else {
head = currNode->next;
delete currNode;
}
return currIndex; head currNode
}
return 0;
}
Printing all the elements
 void DisplayList(void)
 Print the data of all the elements
 Print the number of the nodes in the list

void List::DisplayList()
{
int num = 0;
Node* currNode = head;
while (currNode != NULL){
cout << currNode->data << endl;
currNode = currNode->next;
num++;
}
cout << "Number of nodes in the list: " << num << endl;
}
Destroying the list
 ~List(void)
 Use the destructor to release all the memory used by the list.
 Step through the list and delete each node one by one.

List::~List(void) {
Node* currNode = head, *nextNode = NULL;
while (currNode != NULL)
{
nextNode = currNode->next;
// destroy the current node
delete currNode;
currNode = nextNode;
}
}
Using List
6
int main(void)
7
result
{ 5
List list; Number of nodes in the list: 3
list.InsertNode(0, 7.0); // successful 5.0 found
4.5 not found
list.InsertNode(1, 5.0); // successful 6
list.InsertNode(-1, 5.0); // unsuccessful 5
list.InsertNode(0, 6.0); // successful Number of nodes in the list: 2

list.InsertNode(8, 4.0); // unsuccessful


// print all the elements
list.DisplayList();
if(list.FindNode(5.0) > 0) cout << "5.0 found" << endl;
else cout << "5.0 not found" << endl;
if(list.FindNode(4.5) > 0) cout << "4.5 found" << endl;
else cout << "4.5 not found" << endl;
list.DeleteNode(7.0);
list.DisplayList();
return 0;
}

You might also like