You are on page 1of 12

University of Mhamed Bouguera Boumerdes

Institute of Electrical and Electronic Engineering

Option: Computer Engineering


M02/EE422: Data structures and algorithms

Laboratory experiment #2

Lab Instructor:
Dr. SAHNOUN

Prepared by:
Tareq SI SALEM

Due March, 7th, 2016

Introduction:
A list is a tool that can be used to store multiple pieces of information at once. It can also be defined as a
variable containing multiple other variables. A list consists of numbers paired with items (items can take any
type).
In this laboratory experiment well deal with list in both their implementations (pointers or using arrays), but
with a constrain that the list must be kept in an increasing order for each operation we do on it.
Implementation:

A solution to this problem is given using C/C++

#include <iostream>
#include <cstdio>
const int MAX = 10;
// MAX specifies the maximum size the list can take
// in the array case.
using namespace std;

// compares two strings according to Alphabetical order


// if a string is greater than the other returns 1
// if less return -1
// otherwise 0
// if a string is a substring of the other
// the largest is greater so:
// aaaa > aaa > aa > a
// a > b and a == a
// ab < aa and aa = aa
// ..
int str_compare(char *a, char *b) {
int i = 0;
while (true) {
if (a[i] == '\0' && b[i] == '\0') {
return 0;
} else if (b[i] == '\0' || a[i] > b[i]) {
return 1;
} else if (a[i] == '\0' || a[i] < b[i]) {
return -1;
} else i++;
}
}

namespace PartA {
// we used separate name spaces
// for array and pointer implementation
typedef struct List {
char *names[MAX];
// a string field to hold names.
int size;
// size of the List must not exceed MAX;
// usually with array lists (Like in Java) it has a capacity variable
// that increases whenever the list is near to be full
// and copies old data to a new array with a larger capacity
} List;
// list is passed by reference
// so a change that happens within the function
// changes the list (not its copy)
int init(List &l) {
l.size = 0;
// initialize the list by setting size to 0
// the list is initially empty
}

// inserts a name:"string" at position p


// With few constrains
// p should be between 0 and list size otherwise p is out of range
// The name added should be less or equal names[p] and if p not equal to 0
// name must be greater or equal to names[p-1]
// otherwise adding the name will make the list unordered
void insert(List &list, int p, char *name) {
if (list.size < MAX) {
if (p <= list.size && p >= 0) {
if (list.size == 0 && p == 0) {
list.names[0] = name;
list.size++;
} else if (p == list.size && str_compare(name, list.names[p - 1]) >= 0) {
list.names[list.size] = name;
list.size++;
} else {
if ((p == 0 && str_compare(name, list.names[p]) <= 0) ||

(str_compare(name, list.names[p]) <= 0 && str_compare(name,


list.names[p - 1]) >= 0)
) {
for (int i = list.size; i >= p; i--)
list.names[i + 1] = list.names[i];
// shift names to the right of the list starting from p to
// list size
list.names[p] = name;
list.size++;
// a name element is added so the list size is increased
} else {
cout << "Cannot insert a new name to maintain the list order" << endl;
}
}
} else {
cout << "Position is out of list range" << endl;
}
} else {
cout << "List is full can't add more elements" << endl;
}
}

// remove an element from the list if it's


// between the start of the list and its end
// otherwise we can't delete an element that's not in the list
//
void remove(List &list, int p) {
if (p < list.size && p >= 0) {
for (int i = p; i < list.size - 1; i++)
list.names[i] = list.names[i + 1];
// shift the list to the left until p
list.size--;
// and decrement size because name
// at position p is deleted
} else {
cout << "Position is out of list range" << endl;
}
}
// a simple linear search to stop when
// we find an occurrence of name in the list
// returns it's index in the list
// if not found returns -1
int find(List &list, char* name) {

for (int i = 0; i < list.size; i++) {


if (str_compare(list.names[i], name) == 0) {
return i;
}
}
return -1;
}
// print the list in increasing order
void traverseForward(List list) {
if (list.size != 0) {
cout << "List(forward): [ ";
for (int i = 0; i < list.size; i++) {
cout << list.names[i] << " ";
}
cout << "]" << endl;
} else {
cout << "List is empty" << endl;
}
}
// print the list in decreasing order
void traverseBackward(List list) {
if (list.size != 0) {
cout << "List(backward): [ ";
for (int i = list.size - 1; i >= 0; i--) {
cout << list.names[i] << " ";
}
cout << "]" << endl;
} else {
cout << "List is empty" << endl;
}
}
}
namespace PartB {
// the name space of part B pointer implementation
struct ListItem {
char *name;
// a string field to represent cell value.
ListItem *next;
// a pointer to the next cell (to be linked to)
};
typedef ListItem* LinkedList;
// defining a linked list (pointer to cells)

int init(LinkedList &list) {


list = NULL;
// initially the list is empty
// so it points to NULL (no cell)
}
// Same as in the array implementation we have to respect the same conditions
void insert(LinkedList &list, int p, char *name) {
if (p == 0) {
if (list == NULL || str_compare(name, list->name) <= 0) {
// if the cell is added to the head of the list
// we only need to check if the new cell
// has a name less or equal to the current head cell name
// if the list is empty we don't need to compare
LinkedList item = new ListItem;
item->name = name;
item->next = list;
list = item;
} else {
cout << "Cannot insert a new name to maintain the list order" << endl;
}
} else {
LinkedList temp = list;
// create a new pointer temp to not change the original list
int count = 0;
// count to keep track of the current position in the list
while (count < p - 1 && temp != NULL) {
// if current position is less than p - 1 stop the loop
// or stop it when temp == NULL (end of the list)
temp = temp->next;
// next cell is assigned to current cell
// traverse the list
count++;
}
if (temp != NULL) {
if (temp->next == NULL && str_compare(name, temp->name) >= 0 ||
// if it's the tail of the list
// just compare with the old tail cell
(str_compare(name, temp->name) >= 0
&& str_compare(name, temp->next->name) <= 0)
// if not the tail nor the head cell of the list
// we need to compare with cellp and cellp+1
) {
LinkedList item = new ListItem;
item->name = name;
item->next = temp->next;

temp->next = item;
// old list cellp-1 -> cellp ->cellp+1
// new list cellp-1 -> newcell -> cellp->cellp+1
} else {
cout << "Cannot insert a new name to maintain the list order" << endl;
}
} else {
cout << "position out of list range" << endl;
}
}
}
// delete a cell from the list
//
void remove(LinkedList &list, int p) {
LinkedList temp = list;
int count = 0;
if (list != NULL) {
if (p == 0) {
LinkedList temp2 = temp;
temp = temp->next;
delete temp2;
} else {
while (count < p - 1 && temp != NULL) {
temp = temp->next;
count++;
}
if (temp != NULL) {
LinkedList temp2 = temp->next;
temp->next = temp2->next;
delete temp2;
} else {
cout << "position out of list range" << endl;
}
}
} else {
cout << "The list is empty" << endl;
}
}
//

print the content of the list in increasing order

void traverseForward(LinkedList list) {


if (list != NULL) {
cout << "List (forward)[ ";
while (list != NULL) {
cout << list->name << " ";
list = list->next;
}

cout << "]" << endl;


} else {
cout << "The list is empty" << endl;
}
}
// needed to print the list in backward
// because the cout statement isn't reached until
// the tail of the list is reached
// then it prints the list in reverse
void traverse_recursive(LinkedList list) {
if (list != NULL) {
traverse_recursive(list->next);
cout << list->name << " ";
}
}
// calls the recursive traverse
void traverseBackward(LinkedList list) {
if (list != NULL) {
cout << "List (backward)[ ";
traverse_recursive(list);
cout << "]" << endl;
} else {
cout << "The list is empty" << endl;
}
}
// a simple linear search to stop when
// we find an occurrence of name in the list
// returns it's index in the list
// if not found returns -1
int find(LinkedList list, char* name) {
int count = 0;
while (list != NULL) {
if (str_compare(name, list->name) == 0)
return count;
else
count++;
list = list->next;
}
// if the list end reached
// implies no occurrence of name was
// found in the list
if (list == NULL)
return -1;
}
}

int main() {
cout << "Where do you want to store names ?" << endl;
cout << "1. Array list " << endl;
cout << "2. Linked list" << endl;
char optionI, optionII;
char *name;
int p, index;
bool loop = true;
PartA::List arrayList;
PartA::init(arrayList);
PartB::LinkedList linkedList;
PartB::init(linkedList);
cout << "option: ";
cin >> optionI;
cout << "1. insert new item" << endl;
cout << "2. delete an item" << endl;
cout << "3. find an item" << endl;
cout << "4. print the list in increasing order" << endl;
cout << "5. print the list in decreasing order" << endl;
cout << "q. to exit" << endl;
while (loop) {
cout << "Select option: ";
cin >> optionII;
cin.ignore();
name = new char[10];
if (optionI == '1') {
switch (optionII) {
case '1':
cout << "Enter name: ";
cin.getline(name, 10);
cout << "Enter position: ";
cin >> p;
PartA::insert(arrayList, p, name);
break;
case '2':
cout << "Enter position: ";
cin >> p;
PartA::remove(arrayList, p);
break;
case '3':
cout << "Enter name to find: ";
cin.getline(name, 10);
index = PartA::find(arrayList, name);
if (index != -1) {
cout << "name found at: " << index << endl;
} else {
cout << "name not found" << endl;
}

break;
case '4':
PartA::traverseForward(arrayList);
break;
case '5':
PartA::traverseBackward(arrayList);
break;
case 'q':
loop = false;
break;
}
} else {
switch (optionII) {
case '1':
cout << "Enter name: ";
cin.getline(name, 10);
cout << "Enter position: ";
cin >> p;
PartB::insert(linkedList, p, name);
break;
case '2':
cout << "Enter position: ";
cin >> p;
PartB::remove(linkedList, p);
break;
case '3':
cout << "Enter name to find: ";
cin.getline(name, 10);
index = PartB::find(linkedList, name);
if (index != -1) {
cout << "name found at: " << index << endl;
} else {
cout << "name not found" << endl;
}
break;
case '4':
PartB::traverseForward(linkedList);
break;
case '5':
PartB::traverseBackward(linkedList);
break;
case 'q':
loop = false;
break;
}
}
cout << "------------------------" << endl;
}

return 0;
}

Testing the functionality of this program:


- Array Implementation
Where do you want to store names ?

------------------------

1. Array list

Select option: 1

2. Linked list

Enter name: aac

option: 1

Enter position: 1

1. insert new item

------------------------

2. delete an item

Select option: 4

3. find an item

List(forward): [ a aac b caa ]

4. print the list in increasing order

------------------------

5. print the list in decreasing order

Select option: 5

q. to exit

List(backward): [ caa b aac a ]

Select option: 1

------------------------

Enter name: a

Select option: 2

Enter position: 0

Enter position: 0

------------------------

------------------------

Select option: 1

Select option: 4

Enter name: b

List(forward): [ aac b caa ]

Enter position: 1

------------------------

------------------------

Select option: 3

Select option: 1

Enter name to find: caa

Enter name: caa

name found at: 1

Enter position: 3

------------------------

Position is out of list range

Select option: 3

------------------------

Enter name to find: adf

Select option: 1

name not found

Enter name: caa

------------------------

Enter position: 2

Select option: q

------------------------

------------------------

Select option: 4
List(forward): [ a b caa ]

- Pointers Implementation
Where do you want to store names ?

------------------------

1. Array list

Select option: 1

2. Linked list

Enter name: ab

option: 2

Enter position: 1

1. insert new item

------------------------

2. delete an item

Select option: 4

3. find an item

List (forward)[ a ab b c ]

4. print the list in increasing order

------------------------

5. print the list in decreasing order

Select option: 2

q. to exit

Enter position: 1

Select option: 5

------------------------

The list is empty

Select option: 4

------------------------

List (forward)[ a b c ]

Select option: 1

------------------------

Enter name: a

Select option: 3

Enter position: 0

Enter name to find: c

------------------------

name found at: 2

Select option: 1

------------------------

Enter name: b

Select option: 3

Enter position: 1

Enter name to find: h

------------------------

name not found

Select option: 1

------------------------

Enter name: c

Select option: 1

Enter position: 2

Enter name: e

------------------------

Enter position: 1

Select option: 4

Cannot insert a new name to maintain

List (forward)[ a b c ]

the list order

------------------------

------------------------

Select option: 5

Select option: q

List (backward)[ c b a ]

------------------------

The two implementation give identical results as expected.


Conclusion:
In this lab experiment we dealt with lists and specifically a list of names (strings), and how to implement them
using both arrays and pointers with a constrain of keeping the list in increasing order for each operation, and see
that a linked list doesnt limit its size but changes dynamically which is an advantage of fixed size arrays.