Sunteți pe pagina 1din 40

Review on linked lists

Motivation
☛ A “List” is a useful structure to hold a collection of
data.
■ Currently, we use arrays for lists

☛ Examples:
List of ten students marks
int studentMarks[10];

List of temperatures for the last two weeks


double temperature[14];
Motivation
☛ list using static array
int myArray[1000];
int n;
We have to decide (to oversize) in advance the size of the array
(list)
☛ list using dynamic array
int* myArray;
int n;
cin >> n;
myArray = new int[n];

We allocate an array (list) of any specified size while the


program is running

☛ linked-list (dynamic size)


size = ??
The list is dynamic. It can grow and shrink to any size.
Array naturally represents a (ordered) list,
the link is implicit, consecutive and contiguous!
Now the link is explicit, any places!

Data
20 45 75 85
0 1 2 array
Link
Link
Data 45 linked list
85
20
75

Data Link
20 45 75 85
Linked Lists: Basic Idea
☛ A linked list is an ordered collection of data
☛ Each element of the linked list has
■ Some data
■ A link to the next element
☛ The link is used to chain the data
Example: A linked list of integers:

Data Link
20 45 75 85
Linked Lists: Basic Ideas
☛ The list can grow and shrink
20 45

addEnd(75), addEnd(85)

20 45 75 85

deleteEnd(85), deleteHead(20), deleteHead(45)

75
Linked Lists: Operations
☛ Original linked list of integers:

20 45 75 85

☛ Insertion (in the middle):


old value
20 45 75 85

60
☛ Deletion (in the middle)

20 45 75 85
deleted item
Definition of linked list type:

struct Node{
int data;
Node* next;
};

We can also:

typedef Node* NodePtr;


Linked List Structure
☛ Node : Data + Link
■ Definition
struct Node {
int data; //contains useful information
Node* next; //points to next element or NULL
};
■ Create a Node
Node* p;
p = new Node; //points to newly allocated memory
■ Delete a Node
delete p;
■ Access fields in a node
(*p).data; //access the data field
(*p).next; //access the pointer field
Or it can be accessed this way
p->data //access the data field
p->next //access the pointer field
Representing and
accessing linked lists
Head
20 45 75 85

☛ We define a pointer

Node* head;

that points to the first node of the linked list. When the
linked list is empty then head is NULL.
Passing a Linked List
to a Function
It is roughly the same as for an array!!!

☛ When passing a linked list to a function it should suffice to pass


the value of head. Using the value of head the function can
access the entire list.

☛ Problem: If a function changes the beginning of a list by inserting


or deleting a node, then head will no longer point to the
beginning of the list.

☛ Solution: When passing head always pass it by reference (not


good!)
or using a function to return a new pointer value
Implementation of an
(Unsorted) Linked List
Start the first node
from scratch

head = NULL;
Head

Node* newPtr; 20
Head
newPtr = new Node;
newPtr->data = 20; newPtr
newPtr->next = NULL;
head = newPtr;
Inserting a Node
at the Beginning
newPtr = new Node;
newPtr->data = 13;
newPtr->next = Head;
head = newPtr;

20
Head

13

newPtr
Keep going …

Head
50 40 13 20

newPtr
Adding an element to the head:
NodePtr&

void addHead(Node*& head, int newdata){

Node* newPtr = new Node; Call by reference, scaring!!!

newPtr->data = newdata;
newPtr->next = Head;
head = newPtr;
}
Also written (more functionally, better!) as:

Node* addHead(Node* head, int newdata){

Node* newPtr = new Node;

newPtr->data = newdata;
newPtr->next = Head;

return newPtr;
}

Compare it with ‘addHead’ with a dynamic array implementation


Deleting the Head Node
Node* p;

p = head;
head = head->next;
delete p;

head (to delete)


50 40 13 20

p
void deleteHead(Node*& head){

if(head != NULL){
NodePtr p = head;
head = head->next;
delete p;
}
}

As a function:
Node* deleteHead(Node* head){

if(head != NULL){
NodePtr p = head;
head = head->next;
delete p;
}

return head;
}
Displaying a Linked List
p = head;
head
20 45

p = p->next;
head
20 45

p
A linked list is displayed by walking through its nodes one by one,
and displaying their data fields (similar to an array!).

void displayList(Node* head){


NodePtr p;
p = head;
while(p != NULL){
cout << p->data << endl;
p = p->next;
}
}

For an array:
void displayArray(int data[], int size) {
int n=0;
while ( n<size ) {
cout << data[i] << endl;
n++;
}

}
Searching for a node (look at array
searching first!)
//return the pointer of the node that has data=item
//return NULL if item does not exist

Node* searchNode(Node* head, int item){


NodePtr p = head;
NodePtr result = NULL;
bool found=false;
while((p != NULL) && (!found)){
if(p->data == item) {
found = true;
result = p;}
p = p->next;
}
return result;
}
Remember array searching algorithm:

void main() {
const int size=8;
int data[size] = { 10, 7, 9, 1, 17, 30, 5, 6 };
int value;
cout << "Enter search element: ";
cin >> value;
int n=0;
int position=-1;
bool found=false;
while ( (n<size) && (!found) ) {
if(data[n] == value) {
found=true;
position=n;}
n++;
}
if(position==-1) cout << "Not found!!\n";
else cout << "Found at: " << position << endl;
}

It is essentially the same!


Variations of linked lists
☛ Unsorted linked lists

☛ Sorted linked lists

☛ Circular linked lists


☛ Doubly linked lists
☛…
Further considerations for the
unsorted lists:

☛ Physical copy of list for operators like


‘delection’ and ‘addHead’
☛ ‘delete’ should be understood as a
decomposition into a sub-list …
Node* deleteHead(Node* head){

// physically copy head into a new one, newhead


// so to keep the original list intact!
Node* newhead …

if(newhead != NULL){
Node* p = newhead;
newhead = newhead->next;
delete p;
}

return newhead;
}
More operation:
adding to the end
☛ Original linked list of integers:

50 40 13 20

☛ Add to the end (insert at the end):

50 40 13 20 60

Last element
The key is how to locate the last element or node of the list!
Add to the end:
void addEnd(NodePtr& head, int newdata){
NodePtr newPtr = new Node;
newPtr->data = newdata;
newPtr->next = NULL;

NodePtr last = head;


if(last != NULL){ // general non-empty list case
while(last->next != NULL)
last=last->next;

last->next = newPtr;
}
else // deal with the case of empty list
head = newPtr;
}

Link new object to last->next


Link a new object to empty list
Add to the end as a function:

NodePtr addEnd(NodePtr head, int newdata){


NodePtr newPtr = new Node;
newPtr->data = newdata;
newPtr->next = NULL;

NodePtr last = head;


if(last != NULL){ // general non-empty list case
while(last->next != NULL)
last=last->next;

last->next = newPtr;
}
else // deal with the case of empty list
head = newPtr;

return head;
}
Implementation of a
Sorted Linked List
Inserting a Node
1. (a) Create a new node using:
NodePtr newPtr = new node;
(b) Fill in the data field correctly.
2. Find “prev” and “cur” such that
the new node should be inserted between *prev and *cur.
3. Connect the new node to the list by using:
(a) newPtr->next = cur;
(b) prev->next = newPtr;

Head
20 45 75 ...

prev 33 cur

newPtr
Finding prev and cur
Suppose that we want to insert or delete a node with
data value newValue. Then the following code
successfully finds prev and cur such that
prev->data < newValue <= cur->data
It’s a kind of search algo,

prev = NULL;

cur = head;
found=false;
while( (cur!=NULL) && (!found) ) {
if (newValue > cur->data) {
prev=cur;
cur=cur->next;
}
else found = true;
}

Prev is necessary as we can’t go back!


Finally, it is equivalent to:

prev = NULL;
cur = head;
while( (cur!=NULL) && (newValue>cur->data) ) {
prev=cur;
cur=cur->next;
}

Logical AND (&&) is short-circuited, sequential, i.e. if the first


part is false, the second part will not be executed.
//insert item into linked list according to ascending order
Node* insertNode(Node* head, int item){
NodePtr newp, cur, pre;
newp = new Node;
newp->data = item;

pre = NULL;
cur = head;
while( (cur != NULL) && (item>cur->data)){
pre = cur;
cur = cur->next;
}

if(pre == NULL){ //insert to head of linked list


newp->next = head;
head = newp; If the position happens to be the head
} else {
pre->next = newp;
new->next = cur;
} General case

return head;
}
// not recommended void type function
void insertNode(NodePtr& head, int item){
NodePtr newp, cur, pre;
newp = new Node;
newp->data = item;

pre = NULL;
cur = head;
while( (cur != NULL) && (item>cur->data)){
pre = cur;
cur = cur->next;
}

if(pre == NULL){ //insert to head of linked list


newp->next = head;
head = newp;
} else {
pre->next = newp;
new->next = cur;
}
}
Deleting a Node
☛ To delete a node from the list
1. Locate the node to be deleted
(a) cur points to the node.
(b) prev points to its predecessor
2. Disconnect node from list using:
prev->next = cur->next;
3. Return deleted node to system:
delete cur;

Head (to delete)


20 45 75 85 ...

prev cur
Delete an element in a sorted linked list:

Node* deleteNode(Node* head, int item){


NodePtr prev=NULL, cur = head;
while( (cur!=NULL) && (item > cur->data)){ Get the location
prev = cur;
cur = cur->next;
}

if ( cur!==NULL && cur->data==item) {

We can delete only if the element is present!


if(cur==head) If (cur==NULL || cur->data!=item) Item is not in the list!
head = head->next;
else
prev->next = cur->next; If the element is at the head

delete cur; General case


}

return head;
}
// in a void function, not recommended

void deleteNode(NodePtr& head, int item){


NodePtr prev=NULL, cur = head;
Get the location
while( (cur!=NULL) && (item > cur->data)){
prev = cur;
cur = cur->next;
}

if ( cur!==NULL && cur->data==item) {


We can delete only if the element is present!
If (cur==NULL || cur->data!=item) Item is not in the list!
if(cur==Head)
Head = Head->next;
else If the element is at the head
prev->next = cur->next;

delete cur;
General case
}
}

S-ar putea să vă placă și