You are on page 1of 21

MINISTRY OF EDUCATION, CULTURE AND RESEARCH

OF THE REPUBLIC OF MOLDOVA


Technical University of Moldova
Faculty of Computers, Informatics and Microelectronics
Department of Software and Automation Engineering

GEORGE RĂBUȘ

Report
Laboratory Work No.2

of the "Data Structures and Algorithms" course

Verificat:
Burlacu Natalia, PhD, associate professor
Department of Software and Automation Engineering,
Facultatea FCIM, UTM

Chisinau – 2023

21
The structure of the report for the laboratory work in the "Data
Structures and Algorithms" course will contain:

1. The purpose of the laboratory work (formulated by the student according


to the problem to be solved);
2. For each task should be written the condition/conditions of the problems;
3. The program code, having relevant comments in it will be present for
each given task;
4. For each task should be shown the screenshot of the code execution (in all
aspects of the code run);
5. The student's conclusions regarding the content of the laboratory work
with personal reflections on what was achieved.
6. The name and surname of the student/teacher and no. the laboratory work
should be modified according to didactical requirements.

Note:
 The report pages should be numbered in the footer, center area;
 The text from items 1 & 2; 4 & 5 have to be written in Times New Roman, font
size 14 pt;
 The space between the lines will be set at 1,5 lines.
 Item 3 of this list (the developed program code should be written in relation to
Courier New, font size 10 pt; the space between code lines being 1.15 lines).
 The report should be uploaded for checking by the lab teacher in the right
Report section (numbered in the same mode as your task) according to the
deadline terms specified by your teacher.

21
1)
The purpose of this laboratory was to familiarize myself and to be able to work
with new sorting alogirthms like shell sort, quicksort and counting merge.
2)

21
3)
Program Task1:
#include <stdio.h>
#include <math.h>

void swap(int *a, int *b){


int aux = *a;
*a = *b;
*b = aux;
}

void print_array(int *a, int n){


for (int i = 0; i < n; i++){
printf("%d ", *(a+i));
}
printf("\n");
}

void task1(int *a, int n){


int min = a[0];
int index_min = 0;
int index_max = 0;
int max = a[0];
for (int i = 0; i < n; i++){
if (*(a+i) < min){
min = *(a+i);
index_min = i;
}
if (*(a+i) > max){
max = *(a+i);
index_max = i;
}
}
// printf("Min: %d, index: %d\n", min, index_min);
// printf("Max: %d, index: %d\n", max, index_max);

21
for (int i = index_min + 1; i < trunc(index_max-index_min)/2 + index_min;
i++) {
int j = index_max - (i - index_min);
swap(&(*(a+i)), &(*(a+j)));
}
}

void task2(int *a,int *b, int n){


print_array(a, n);
print_array(b, n);
}

// function to find the partition position


int partition(int *array, int low, int high) {

// select the rightmost element as pivot


int pivot = *(array + high);

// pointer for greater element


int i = (low - 1);

// traverse each element of the array


// compare them with the pivot
for (int j = low; j < high; j++) {
if (*(array + j) <= pivot) {

// if element smaller than pivot is found


// swap it with the greater element pointed by i
i++;

// swap element at i with element at j


swap(&(*(array + i)), &(*(array + j)));
}
}

// swap the pivot element with the greater element at i


swap(&(*(array + i + 1)), &(*(array + high)));

// return the partition point

21
return (i + 1);
}

int partition2(int *array, int low, int high) {


// select the rightmost element as pivot
int pivot = *(array + high);

// pointer for greater element


int i = (low - 1);

// traverse each element of the array


// compare them with the pivot
for (int j = low; j < high; j++) {
if (*(array +j) >= pivot) { // Change this line to reverse the sorting
order
// if element greater than pivot is found
// swap it with the smaller element pointed by i
i++;

// swap element at i with element at j


swap(&(*(array + i)), &(*(array + j)));
}
}

// swap the pivot element with the smaller element at i


swap(&(*(array + i + 1)), &(*(array + high )));

// return the partition point


return (i + 1);
}

void task3(int *array, int low, int high) {


if (low < high) {

// find the pivot element such that


// elements smaller than pivot are on left of pivot
// elements greater than pivot are on right of pivot
int pi = partition(array, low, high);

21
// recursive call on the left of pivot
task3(array, low, pi - 1);

// recursive call on the right of pivot


task3(array, pi + 1, high);
}
}
void task3_2(int *array, int low, int high) {
if (low < high) {

// find the pivot element such that


// elements smaller than pivot are on left of pivot
// elements greater than pivot are on right of pivot
int pi = partition2(array, low, high);

// recursive call on the left of pivot


task3_2(array, low, pi - 1);

// recursive call on the right of pivot


task3_2(array, pi + 1, high);
}
}

void task4(int *array, int n) {


// Rearrange elements at each n/2, n/4, n/8, ... intervals
for (int interval = n / 2; interval > 0; interval /= 2) {
for (int i = interval; i < n; i += 1) {
int temp = *(array + i);
int j;
for (j = i; j >= interval && *(array + j - interval) > temp; j -=
interval) {
*(array + j) = *(array + j - interval);
}
*(array + j) = temp;
}
}
}

void task4_2(int *array, int n) {

21
// Rearrange elements at each n/2, n/4, n/8, ... intervals
for (int interval = n / 2; interval > 0; interval /= 2) {
for (int i = interval; i < n; i += 1) {
int temp = *(array + i);
int j;
for (j = i; j >= interval && *(array+j - interval) < temp; j -=
interval) {
*(array + j) = *(array+j - interval);
}
*(array + j) = temp;
}
}
}

int main() {
int n;
scanf("%d", &n);
int a_original[50];
int a_modified[50];
for (int i = 0; i < n; i++)
scanf("%d", &a_original[i]);
for (int i = 0; i < n; i++)
{a_modified[i] = a_original[i];}
printf("\nTasks:\n\n");
task1(a_modified,n);
printf("Display the original and modified arrays:\n");
task2(a_original,a_modified,n);
printf("Display the original array after quick-sorting:\n");
task3(a_original, 0, n - 1);
print_array(a_original, n);
task3_2(a_original, 0, n - 1);
print_array(a_original, n);
printf("Display the modified array after shell-sorting:\n");
task4(a_modified,n);
print_array(a_modified, n);
task4_2(a_modified,n);
print_array(a_modified, n);
return 0;
//-18 10 -3 7 28 55 -4
}

21
Program Task2:
#include <stdio.h>
#include <stdlib.h>

void swap(int *a, int *b) {


int aux = *a;
*a = *b;
*b = aux;
}

void print_array(int *a, int n) {


for (int i = 0; i < n; i++) {
printf("%d ", *(a + i));
}
printf("\n");
}

void task1(int *a, int n) {


int min = a[0];
int index_min = 0;
int index_max = 0;
int max = a[0];
for (int i = 0; i < n; i++) {
if (*(a + i) < min) {
min = *(a + i);
index_min = i;
}
if (*(a + i) > max) {
max = *(a + i);
index_max = i;
}
}

21
for (int i = index_min + 1; i < (index_max - index_min) / 2
+ index_min; i++) {
int j = index_max - (i - index_min);
swap(&(*(a + i)), &(*(a + j)));
}
}

void task2(int *a, int *b, int n) {


print_array(a, n);
print_array(b, n);
}

void merge(int *arr, int l, int m, int r) {


int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;

// Create temp arrays on the stack


int *L = malloc(n1 * sizeof(int));
int *R = malloc(n2 * sizeof(int));

// Check for memory allocation errors


if (L == NULL || R == NULL) {
fprintf(stderr, "Memory allocation error\n");
exit(EXIT_FAILURE);
}

// Copy data to temp arrays L[] and R[]


for (i = 0; i < n1; i++)
*(L + i) = *(arr + l + i);
for (j = 0; j < n2; j++)
*(R + j) = *(arr + m + 1 + j);

21
// Merge the temp arrays back into arr[l..r]
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (*(L + i) <= *(R + j)) {
*(arr + k) = *(L + i);
i++;
} else {
*(arr + k) = *(R + j);
j++;
}
k++;
}

// Copy the remaining elements of L[], if there are any


while (i < n1) {
*(arr + k) = *(L + i);
i++;
k++;
}

// Copy the remaining elements of R[], if there are any


while (j < n2) {
*(arr + k) = *(R + j);
j++;
k++;
}

// Free the dynamically allocated memory


free(L);
free(R);
}

21
void mergeSort(int *arr, int l, int r) {
if (l < r) {
int m = l + (r - l) / 2;

// Sort first and second halves


mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);

merge(arr, l, m, r);
}
}

void merge2(int *arr, int l, int m, int r) {


int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;

// Create temp arrays on the stack


int *L = malloc(n1 * sizeof(int));
int *R = malloc(n2 * sizeof(int));

// Check for memory allocation errors


if (L == NULL || R == NULL) {
fprintf(stderr, "Memory allocation error\n");
exit(EXIT_FAILURE);
}

// Copy data to temp arrays L[] and R[]


for (i = 0; i < n1; i++)
*(L + i) = *(arr + l + i);
for (j = 0; j < n2; j++)
*(R + j) = *(arr + m + 1 + j);

21
// Merge the temp arrays back into arr[l..r]
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (*(L + i) >= *(R + j)) {
*(arr + k) = *(L + i);
i++;
} else {
*(arr + k) = *(R + j);
j++;
}
k++;
}

// Copy the remaining elements of L[], if there are any


while (i < n1) {
*(arr + k) = *(L + i);
i++;
k++;
}

// Copy the remaining elements of R[], if there are any


while (j < n2) {
*(arr + k) = *(R + j);
j++;
k++;
}

// Free the dynamically allocated memory


free(L);
free(R);

21
}

void mergeSort2(int *arr, int l, int r) {


if (l < r) {
int m = l + (r - l) / 2;

// Sort first and second halves


mergeSort2(arr, l, m);
mergeSort2(arr, m + 1, r);

merge2(arr, l, m, r);
}
}

void countingSort(int *array, int size) {


int output[10];

// Find the largest element of the array


int max = *array;
for (int i = 1; i < size; i++) {
if (*(array + i) > max)
max = *(array + i);
}

// The size of count must be at least (max+1) but


// we cannot declare it as int count(max+1) in C as
// it does not support dynamic memory allocation.
// So, its size is provided statically.
int count[100];

// Initialize count array with all zeros.


for (int i = 0; i <= max; ++i) {
*(count + i) = 0;

21
}

// Store the count of each element


for (int i = 0; i < size; i++) {
(*(count + *(array + i)))++;
}

// Store the cumulative count of each array


for (int i = 1; i <= max; i++) {
*(count + i) += *(count + (i - 1));
}

// Find the index of each element of the original array in


count array, and
// place the elements in the output array
for (int i = size - 1; i >= 0; i--) {
*(output + (*(count + *(array + i))) - 1) = *(array + i);
(*(count + *(array + i)))--;
}

// Copy the sorted elements into the original array


for (int i = 0; i < size; i++) {
*(array + i) = *(output + i);
}
}

void countingSort2(int *array, int size) {


int output[100];

// Find the largest element of the array


int max = *array;
for (int i = 1; i < size; i++) {
if (*(array + i) > max)

21
max = *(array + i);
}

// The size of count must be at least (max+1)


int count[max + 1]; // Changed to dynamic allocation for
flexibility

// Initialize count array with all zeros.


for (int i = 0; i <= max; ++i) {
*(count + i) = 0;
}

// Store the count of each element


for (int i = 0; i < size; i++) {
(*(count + *(array + i)))++;
}

// Store the cumulative count of each array


for (int i = 1; i <= max; i++) {
*(count + i) += *(count + (i - 1));
}

// Find the index of each element of the original array in


count array, and
// place the elements in the output array
for (int i = size - 1; i >= 0; i--) {
*(output + (*(count + *(array + i))) - 1) = *(array + i);
(*(count + *(array + i)))--;
}

// Copy the sorted elements into the original array in


decreasing order
for (int i = 0; i < size; i++) {

21
*(array + i) = *(output + size - i - 1);
}
}

int isTriangle(int a, int b, int c) {


return (a + b > c) && (b + c > a) && (c + a > b);
}

// Function to count triangles in an array of numbers


int countTriangles(int *arr, int n) {
int count = 0;

// Iterate through all possible combinations of three


elements
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
for (int k = j + 1; k < n; k++) {
// Check if the current combination forms a
triangle
if (isTriangle(*(arr + i),*(arr + j), *(arr +
k))) {
count++;
}
}
}
}
}

int main() {
int n;
scanf("%d", &n);
int a_original[50];
int a_modified[50];

21
int a[50];
for (int i = 0; i < n; i++)
scanf("%d", &a_original[i]);
for (int i = 0; i < n; i++)
a_modified[i] = a_original[i];
for (int i = 0; i < n; i++)
a[i] = a_original[i];
printf("\nTasks:\n\n");
task1(a_modified, n);
printf("Display the original and modified arrays:\n");
task2(a_original, a_modified, n);
printf("Display the original array after merge-sorting:\n");
mergeSort(a_original, 0, n - 1);
print_array(a_original, n);
mergeSort2(a_original, 0, n - 1);
print_array(a_original, n);
printf("Display the modified array after count-sorting:\n");
countingSort(a_modified, n);
print_array(a_modified, n);
countingSort2(a_modified, n);
print_array(a_modified, n);
printf("\n");
printf("Additional task: Find in an array how many triangles
can be formed.\n\n");
int triangleCount = countTriangles(a, n);
printf("Number of triangles that can be formed: %d\n",
triangleCount);
return 0;
}

21
FLOWCHARTS:

21
4)
Screenshots:

5)
Conclusion:

21
In conclusion, the laboratory work focused on implementing and understanding
various sorting algorithms, including shell sort, merge sort, quick sort counting sort
as well as developing our creativity on problem solving.

21

You might also like