Lecture 2
Lecture 2
Lists
Outline
3
A B C
Head
A linked list is a series of connected nodes
Each node contains at least
A piece of data (any type)
Pointer to the next node in the list
Head: pointer to the first node
The last node points to NULL node
A
data pointer
A Simple Linked List Class
11
class Node {
public:
double data; // data
Node* next; // pointer to next
};
A Simple Linked List Class
12
class List {
public:
List(void) { head = NULL; } // constructor
~List(void); // destructor
Operations of List
IsEmpty: determine whether or not the list is empty
2. Insert in front
3. Insert at back
4. Insert in middle
and Case 4)
Inserting a new node
Node* List::InsertNode(int index,16double x) { Try to locate
if (index < 0) return NULL; index’th node. If it
doesn’t exist,
int currIndex = 1;
Node* currNode = head; return NULL.
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
int FindNode(double x)
Search for a node with the value equal to x in the list.
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
21
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
void DisplayList(void)
Print the data of all the elements
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
26
~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;
}
}
6
7 result
Using List 5
Number of nodes in the list: 3
5.0 found
27
4.5 not found
6
int main(void) 5
{ Number of nodes in the list: 2
List list;
list.InsertNode(0, 7.0); // successful
list.InsertNode(1, 5.0); // successful
list.InsertNode(-1, 5.0); // unsuccessful
list.InsertNode(0, 6.0); // successful
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;
}
Variations of Linked Lists
28
A B C
Head
How do we know when we have finished
traversing the list? (Tip: check if the pointer of
the current node is equal to the head.)
Variations of Linked Lists
29
A B C
Head
Array versus Linked Lists
30
Direct applications
Undo sequence in a text editor
Indirect applications
Auxiliary data structure for algorithms
Component of other data structures
Array-based Stack
(Implementation)
36
…
S
0 1 2 t
Array-based Stack (cont.)
37
…
S
0 1 2 t
Array-based Stack (Cont.)
38
Performance
Let n be the number of elements in the stack
The space used is O(n)
Limitations
The maximum size of the stack must be
defined a priori and cannot be changed
Trying to push a new element into a full
Algorithm ParenMatch(X,n):
Input: An array X of n tokens, each of which is either a grouping symbol, a
variable, an arithmetic operator, or a number
Output: true if and only if all the grouping symbols in X match
Let S be an empty stack
for i=0 to n-1 do
if X[i] is an opening grouping symbol then
S.push(X[i])
else if X[i] is a closing grouping symbol then
if S.isEmpty() then
return false {nothing to match with}
if S.pop() does not match the type of X[i] then
return false {wrong type}
if S.isEmpty() then
return true {every symbol matched}
else
return false {some symbols were never matched}
Parentheses Matching
Example 1 45
Input: ( () [] ]()
1 ( Push ( ((
2 ) Pop ( (
Test if ( and X[i] match? YES
3 [ Push [ ([
4 ] Pop [ (
Test if [ and X[i] match? YES
5 ] Pop (
Test if ( and X[i] match ? NO FASLE
Summary of Stack
48
• Operations
– MakeEmpty
– Boolean IsEmpty
– Boolean IsFull
– Enqueue (ItemType newItem)
– Dequeue (ItemType& item)
Enqueue (ItemType newItem)
• Function: Adds newItem to the rear of the
queue.
• Preconditions: Queue has been initialized
and is not full.
• Postconditions: newItem is at rear of queue.
Dequeue (ItemType& item)
• Function: Removes front item from queue
and returns it in item.
• Preconditions: Queue has been initialized
and is not empty.
• Postconditions: Front element has been
removed from queue and item is a copy of
removed element.
Implementation issues
• Implement the queue as a circular structure.
• How do we know if a queue is full or
empty?
• Initialization of front and rear.
• Testing for a full or empty queue.
Make front point to the element preceding the front
element in the queue (one memory location will be
wasted).
Initialize front and rear
Queue is empty
now!!
rear == front
Queue Implementation
template<class ItemType> private:
class QueueType { int front;
public: int rear;
QueueType(int); ItemType* items;
QueueType(); int maxQue;
~QueueType(); };
void MakeEmpty();
bool IsEmpty() const;
bool IsFull() const;
void Enqueue(ItemType);
void Dequeue(ItemType&);
Queue Implementation (cont.)
template<class ItemType>
QueueType<ItemType>::QueueType(int
max)
{
maxQue = max + 1;
front = maxQue - 1;
rear = maxQue - 1;
items = new ItemType[maxQue];
}
Queue Implementation (cont.)
template<class ItemType>
QueueType<ItemType>::~QueueType()
{
delete [] items;
}
Queue Implementation (cont.)
template<class ItemType>
void QueueType<ItemType>::
MakeEmpty()
{
front = maxQue - 1;
rear = maxQue - 1;
}
Queue Implementation (cont.)
template<class ItemType>
bool QueueType<ItemType>::IsEmpty() const
{
return (rear == front);
}
template<class ItemType>
bool QueueType<ItemType>::IsFull() const
{
return ( (rear + 1) % maxQue == front);
}
Queue Implementation (cont.)
template<class ItemType>
void QueueType<ItemType>::Enqueue
(ItemType newItem)
{
rear = (rear + 1) % maxQue;
items[rear] = newItem;
}
Queue Implementation (cont.)
template<class ItemType>
void QueueType<ItemType>::Dequeue
(ItemType& item)
{
front = (front + 1) % maxQue;
item = items[front];
}
Queue overflow
if(!q.IsFull())
q.Enqueue(item);
Queue underflow
if(!q.IsEmpty())
q.Dequeue(item);
Example: recognizing palindromes
• A palindrome is a string that reads the same
forward and backward.
Able was I ere I saw Elba
• We will read the line of text into both a stack
and a queue.
• Compare the contents of the stack and the
queue character-by-character to see if they
would produce the same string of characters.
Example: recognizing palindromes
Example: recognizing palindromes
#include <iostream.h> cout << "Enter string: " << endl;
#include <ctype.h>
while(cin.peek() != '\\n') {
#include "stack.h"
#include "queue.h“ cin >> ch;
if(isalpha(ch)) {
int main()
{ if(!s.IsFull())
StackType<char> s; s.Push(toupper(ch));
QueType<char> q; if(!q.IsFull())
char ch; q.Enqueue(toupper(ch));
char sItem, qItem; }
}
int mismatches = 0;
Example: recognizing palindromes
while( (!q.IsEmpty()) && (!s.IsEmpty()) ) {
s.Pop(sItem);
q.Dequeue(qItem);
if(sItem != qItem)
++mismatches;
}
if (mismatches == 0)
cout << "That is a palindrome" << endl;
else
cout << That is not a palindrome" << endl;
return 0;
}
Case Study: Simulation