Selection sort vs. Bubble sort C++ - c++

I made this program to sort a list of numbers. It is supposed to be selection sort, but my teacher said it works more like bubble sort and I need to fix it. Any suggestions on what parts I need to change?
#include <iostream>
using namespace std;
void printArr(const int a[], int s);
void swapVals(int& v1, int& v2);
void sortArr(int a[], int s);
int main()
{
const int s = 20;
int arr[s] = {8, 38, 25, 4, 47, 47, 38, 36, 3, 33, 2, 19, 16, 30, 5, 47, 16,
38, 13, 1
};
cout << "Unsorted array:\n";
printArr(arr, s);
cout << "\n\n";
sortArr(arr, s);
cout << "Sorted Array:\n";
printArr(arr, s);
cout << "\n";
return 0;
}
void sortArr(int a[], int s)
{
for (int i = 0; i < s-1; i++)
{
int index = i;
for (int j = i + 1; j < s; j++)
if (a[j] < a[index])
index = j;
swapVals(a[index], a[i]);
}
}
void swapVals(int& v1, int& v2)
{
int temp = v1;
v1 = v2;
v2 = temp;
}
void printArr(const int a[], int s)
{
for (int i=0; i<s; i++)
{
cout << a[i];
if (i != s-1)
cout << " ";
}
}

I believe it's selection sort, just the way you write the code makes it easy for people to misunderstand.
For which part to change, I'll have to say, it's inside your sortArr function, the inner loop, better to add a comment here "find the index of min starting from i + 1" or you can just call the findMin you have defined. From the call routine: main call sortArr, sortArr only call swap and does not call findMin, it looks really like a bubble sort.
Also, your findMin is not good, it's finding min value, not the index of min value.

Related

How do I write a function that modifies a list such that all odd elements get duplicated and all even elements removed?

I'm trying to write a function that modifies an array list by removing even numbers and duplicating odd numbers.
My code works just fine in removing the even numbers. However, it only duplicates some odd numbers.
For eg. my list contains: 12 11 13 14 15 13 10
The list L after L.duplicateORremove() should contain:
11 11 13 13 15 15 13 13
But this is what I get: 11 13 13 15 13 13
I'd like some help in figuring out why I'm getting this result.
This is my code so far:
template <class Type>
void arrayListType <Type>::duplicateORremove()
{
for(int i=0; i<length; i++)
{
if(list[i]%2==0)
{
for (int j = i; j < length - 1; j++)
list[j] = list[j + 1];
length--;
}
else
{
for (int j = length; j > i; j--)
list[j] = list[j - 1];
list[i+1] = list[i];
i++;
length++;
}
}
}
This is how my class definition and main look like:
template < class Type >
class arrayListType {
public:
arrayListType(int size = 100);
~arrayListType();
void insertEnd(const Type & insertItem);
void print() const;
void duplicateORremove();
protected:
Type * list; //array to hold the list elements
int length; //stores length of list
int maxSize; //stores maximum size of the list
};
template < class Type >
arrayListType < Type > ::arrayListType(int size) {
if (size < 0) {
cerr << "The array size must be positive. Creating " <<
"an array of size 100. " << endl;
maxSize = 100;
} else
maxSize = size;
length = 0;
list = new Type[maxSize];
assert(list != NULL);
}
template < class Type >
arrayListType < Type > ::~arrayListType() {
delete[] list;
}
template < class Type >
void arrayListType < Type > ::insertEnd(const Type & insertItem) {
if (length >= maxSize)
cerr<<"Cannot insert in a full list" << endl;
else {
list[length] = insertItem;
length++;
}
}
template < class Type >
void arrayListType < Type > ::print() const {
for (int i = 0; i < length; i++)
cout << list[i] << " ";
cout << endl;
}
int main()
{
arrayListType <int> L;
L.insertEnd(12);
L.insertEnd(11);
L.insertEnd(13);
L.insertEnd(14);
L.insertEnd(15);
L.insertEnd(13);
L.insertEnd(10);
cout << "List L before L.duplicateORremove() contains:" << endl;
L.print();
L.duplicateORremove();
cout << "List L after L.duplicateORremove() contains:" << endl;
L.print();
#include <iostream>
using namespace std;
void duplicateORremove(int list[], int length) {
for(int i=0; i<length; i++)
{
if(list[i]%2==0)
{
for (int j = i; j < length - 1; j++)
list[j] = list[j + 1];
length--;
i-=1;
}
else
{
for (int j = length; j > i; j--)
list[j] = list[j - 1];
list[i+1] = list[i];
i++;
length++;
}
}
for (int i=0; i<length; i++) {
cout << list[i];
cout << " ";
}
}
int main()
{
int arrlist[] = {12, 11, 13, 14, 15, 13, 10};
duplicateORremove(arrlist, 7);
return 0;
}
You are not resetting the 'i' value to traverse from the previous state when an even number is found. Because of that odd number taking place of an even number is skipped while looping, and, hence you will end up with a result that has some values missing in the result. And the count of missing values will be equal to the count of even number in your input.
Just add that reset condition and it will work.
Link to run the above code: Online cpp compiler
Here's a solution using Range-v3 library.
You can operate on a view of the original range.
Remove the even elements.
Duplicate each element of the remaining list (the odd ones).
Then convert the view back into a vector and return it.
[Demo]
#include <fmt/ranges.h>
#include <range/v3/all.hpp>
template <typename Range>
auto duplicate_or_remove(Range&& r) {
using namespace ranges::v3;
auto even = [](int i) { return 0 == i % 2; };
return r
| views::remove_if(even)
| views::for_each([](auto e){ return yield_from(views::repeat_n(e, 2)); })
| to_vector;
}
int main() {
std::vector<int> v{12, 11, 13, 14, 15, 13, 10};
fmt::print("{}", duplicate_or_remove(v));
}
// Outputs:
//
// [11, 11, 13, 13, 15, 15, 13, 13]
Going back to your code, notice that you cannot simply work over your input list. What would happen if the list only contained odd numbers? For the first element, you would be writing beyond the memory reserved for the list. Instead, if you need to stick to using arrays, what you can do is:
Count the odd elements in your input list.
Create a new array sized twice the number of odd elements in the input list.
Walk over the input list and, for each odd element, add it twice to the newly created array.
Return a pair consisting of the new array and its size.
The code below also uses a nice trick to avoid passing the length of an array to a funcion if what you are passing is an array and not a pointer.
[Demo]
#include <iostream> // cout
#include <utility> // pair
auto is_odd = [](int i){ return (i % 2) == 1; };
template <size_t length>
size_t count_odd_elements(int (&list)[length]) {
size_t ret{};
for (size_t i{0}; i < length; ++i) {
if (is_odd(list[i])) {
ret++;
}
}
return ret;
}
template <size_t length>
auto duplicate_or_remove(int (&list)[length]) {
size_t odd_elements{ count_odd_elements(list) };
size_t ret_size{odd_elements * 2};
int* ret = new int[ret_size];
size_t head{};
for (size_t i{0}; i < length; ++i) {
int n{ list[i] };
if (is_odd(n)) {
ret[head++] = n;
ret[head++] = n;
}
}
return std::pair<int*, size_t>{ret, ret_size};
}
void print_list(int list[], size_t length) {
std::cout << "[";
for (size_t i{0}; i < length; ++i) {
std::cout << ((i == 0) ? "" : ", ") << list[i];
}
std::cout << "]";
}
int main() {
int arrlist[] = {12, 11, 13, 14, 15, 13, 10};
auto [result, result_size] = duplicate_or_remove(arrlist);
print_list(result, result_size);
delete[] result;
}
// Outputs:
//
// [11, 11, 13, 13, 15, 15, 13, 13]
Again, using std::vector instead of arrays simplify things a lot:
[Demo]
#include <fmt/ranges.h>
#include <iostream> // cout
#include <vector>
auto is_odd = [](int i){ return (i % 2) == 1; };
auto duplicate_or_remove(const std::vector<int>& list) {
std::vector<int> ret{};
for (auto i : list) {
if (is_odd(i)) {
ret.push_back(i);
ret.push_back(i);
}
}
return ret;
}
int main() {
std::vector<int> v{12, 11, 13, 14, 15, 13, 10};
auto result{ duplicate_or_remove(v) };
fmt::print("{}", result);
}

C++ Selection Sort not Sorting Some Values of an Array

I am trying to sort an array of integers using a selection sort algorithm, but some of the numbers aren't sorting. Below is the isolated section of my code that does the sorting and the output. Any suggestions?
#include <iostream>
using namespace std;
int main()
{
int smallestIndex;
int temp;
int X[13] = {1, 19, 2, 18, 4, 12, 7, 8, 10, 3, 11, 17, 9};
for (int Index = 0; Index < 12; Index++) {
smallestIndex = Index;
for (int minIndex = Index+1; minIndex < 13; minIndex++) {
if (X[minIndex] < X[smallestIndex]) {
smallestIndex=minIndex;
}
if (smallestIndex != Index) {
temp = X[Index];
X[Index] = X[smallestIndex];
X[smallestIndex] = temp;
}
}
}
for (int i = 0; i < 13; i++) {
cout << X[i] << endl;
}
}
output:
1
2
4
7
9
3
10
8
11
12
17
18
19
There is an easier way to do this by using the swap() function, and using two more functions called, void selectionSort() and void printArray() to make the code look cleaner.
#include <iostream>
#include <algorithm>
void swap(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void selectionSort(int arr[], int n)
{
int i, j, min_idx;
// One by one move boundary of unsorted subarray
for (i = 0; i < n-1; i++)
{
// Find the minimum element in unsorted array
min_idx = i;
for (j = i+1; j < n; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
swap(&arr[min_idx], &arr[i]);
}
}
void printArray(int arr[], int size)
{
int i;
for (i=0; i < size; i++)
std::cout << arr[i] << " ";
std::cout << std::endl;
}
int main()
{
int arr[] = {1, 19, 2, 18, 4, 12, 7, 8, 10, 3, 11, 17, 9};
int n = sizeof(arr)/sizeof(arr[0]);
selectionSort(arr, n);
std::cout << "The sorted array is: \n";
printArray(arr, n);
return 0;
}
Output:
The sorted array is:
1 2 3 4 7 8 9 10 11 12 17 18 19
Another way you could do this is by just strictly using std::swap without the use of pointers. Make sure to include the #include<algorithm> header file for std::swap. You will also need to include #include <iterator> for std::size.
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
int arr[] = {1, 19, 2, 18, 4, 12, 7, 8, 10, 3, 11, 17, 9};
constexpr int length{ static_cast<int>(std::size(arr)) };
//constexpr means that value of a variable can appear in a constant expression.
// Step through each element of the array
for (int startIndex{ 0 }; startIndex < length - 1; ++startIndex)
{
int smallestIndex{ startIndex };
// Then look for a smaller element in the rest of the array
for (int currentIndex{ startIndex + 1 }; currentIndex < length; ++currentIndex)
{
if (arr[currentIndex] < arr[smallestIndex])
smallestIndex = currentIndex;
}
// swap our start element with our smallest element
std::swap(arr[startIndex], arr[smallestIndex]);
}
// Now that the whole array is sorted, print it.
for (int index{ 0 }; index < length; ++index)
std::cout << arr[index] << ' ';
std::cout << '\n';
return 0;
}
You could also just use std::sort instead. It is in the header file #include<algorithm> which just sorts in ascending order by default. You will also need the header file #include <iterator> for std::size
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
int arr[] = {1, 19, 2, 18, 4, 12, 7, 8, 10, 3, 11, 17, 9};
std::sort(std::begin(arr), std::end(arr));
for (int i{ 0 }; i < static_cast<int>(std::size(arr)); ++i)
std::cout << array[i] << ' ';
std::cout << '\n';
return 0;
}

Reversing array but only one element is returning

I'm trying to reverse an array and I think the for loop is wrong but everyone I've shown it to doesn't see a problem.
#include <iostream>
void reverse() {
int temp;
const int size = 9;
int arr[size] = {1, 4, 10, 16, 34, 7, 8, 9, 11};
for (int i=0; i <size-1; i++){
for (int j=size-1; j>=0; j--){
arr[j]= temp;
arr[i] = temp;
}
}
for(int x= 0; x<size; x++){
std::cout<<arr[x]<< " ";
}
}
int main () {
reverse();
return 0;
}
I suggest you use an algorithm of the std, namely std::reverse. You don't have to invent an algorithm, that reverts an array.
Thus your code is reduced to
#include <iostream>
#include <array>
#include <algorithm>
void reverse() {
std::array<int, 9> arr{1, 4, 10, 16, 34, 7, 8, 9, 11};
std::reverse(arr.begin(), arr.end());
for (const auto& item : arr) {
std::cout << item << " ";
}
}
int main() {
reverse();
return 0;
}
Choosing proper container and algorithm form the standard library will significantly enhance the quality (in terms of bugs, readability, ...) and speed up you development. Furthermore, in most cases the runtime of your program will be shorter as well.
#include<iostream>
using namespace std;
void reverse() {
int temp;
const int size = 9;
int arr[size] = {1, 4, 10, 16, 34, 7, 8, 9, 11};
for (int i=0, j =size-1; i <j ; i++, j--)
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
for(int x= 0; x<size; x++){
std::cout<<arr[x]<< " ";
}
}
int main () {
reverse();
return 0;
}
The variable 'temp' in your code is not initialised.
// I think this is what you are trying to do.
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
This would be faster. You just traverse half of the array and switch the elements don't do n² traversion, this is definitely not needed here.
void reverse() {
const int size = 9;
int arr[size] = {1, 4, 10, 16, 34, 7, 8, 9, 11};
int back = size - 1;
int temp;
for( int i = 0; i < size / 2; ++i)
{
temp = arr[i];
arr[i] = arr[back];
arr[back--] = temp;
}
for( auto n : arr )
std::cout << n << " ";
std::cout << std::endl;
}
to your code:
void reverse() {
int temp;
const int size = 9;
int arr[size] = {1, 4, 10, 16, 34, 7, 8, 9, 11};
for (int i=0; i <size-1; i++){
for (int j=size-1; j>=0; j--){ // here every element is set to
// temp, but temp isn initialized so they are set to a random value.
// Try setting temp to 0 and look what happens your whole array should
// become 0.
arr[j]= temp;
arr[i] = temp;
}
}
for(int x= 0; x<size; x++){
std::cout<<arr[x]<< " ";
}
}
check this one to reverse ur array..
#include <iostream>
using namespace std;
void reverse() {
int temp;
const int size = 9;
int arr[size] = {1, 4, 10, 16, 34, 7, 8, 9, 11};
for (int i=8; i>=0; i--){
// cout<<arr[i]<< " ";
std::cout<<arr[i]<< " ";
}
}
int main () {
reverse();
return 0;
}

how to see number movements in c++ boolean?

I have a small program to sort random numbers into the right sequence number. Well, I want to see every random number move. what should be added to it?
#include <iostream>
using namespace std;
void pindah (int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void tukar (int arr[], int n) {
int i, j;
bool trade;
for (i=0; i < n-1; i++) {
trade = false;
for (j=0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
pindah(&arr[j], &arr[j+1]);
trade = true;
}
}
if (trade == false)
break;
}
}
void cetakArray (int arr[], int n) {
int i;
for (i=0; i<n; i++) {
cout << arr[i] << " "; //tampil data
}
}
int main () {
int arr[] = {4, 6, 7, 2, 1, 5, 8, 10, 9, 3};
int n = sizeof(arr) / sizeof(int); //menghitung jumlah data array
cout << "setelah diurutkan : \n";
tukar (arr, n);
cetakArray (arr, n);
}
please help me
Assuming that by "into the right sequence" you mean from small to large, and assuming that you are willing to use C++11, we can easily obtain this with a lambda function. See the following example.
#include <vector>
#include <algorithm>
std::vector<int> values({4, 6, 7, 2, 1, 5, 8, 10, 9, 3});
int number_of_moves = 0;
std::sort(begin(values), end(values), [&](int lhs, int rhs)
{
if (lhs > rhs)
return false;
++number_of_moves;
std::cout << "I am going to swap " << lhs << " with " << rhs << '\n';
return true;
});
std::cout << "I took me " << number_of_moves << " move(s) to sort the vector\n";
Note: it is not clear to me what you mean by "movements in c++ boolean", so I chose to print the numbers that are going to be swapped.
EDIT: based on the comments I guess you want to count the number of movements, so I have added a counter. Note that a bool can only be true/false and cannot be used for counting.

Why is the number of location swaps showing up as zero?

While I'm pretty sure the number of location swaps for everything else is correct, the one for my InsertionSort function is showing up as zero.
I'm not sure why.
Any ideas on how to fix this logic error?
#include <iostream>
using namespace std;
const int SIZE=20;
void bubbleSort(int numbers[], int SIZE);
void selectionSort(int numbers[], int SIZE);
void insertionSort(int numbers[], int SIZE, int &a, int &b);
int main()
{
int numbers[SIZE]= {26, 45, 56, 12, 78, 74, 39, 22, 5, 90, 87, 32, 28, 11, 93, 62, 79, 53, 22, 51};
int value=0;
bool found;
int a;
int b;
cout << "Today we are going to be searching for values." << endl;
cout << "These are the values you have to choose from" << endl;
for (int i=0; i<SIZE; i++)
cout << numbers[i]<<"; ";
do
{
cout << "Make sure to enter a value that's in the list." << endl;
cin >> value;
found=false;
for (int i=0; i<SIZE; i++)
{
if (value==numbers[i])
{
found=true;
break;
}
}
if (!found)
cout << "Enter a valid value !" << endl;
}
while (!found);
bubbleSort(numbers, SIZE);
selectionSort(numbers, SIZE);
insertionSort(numbers, SIZE, a, b);
return 0;
}
void bubbleSort (int numbers[], int SIZE)
{
cout<<"\nOriginal order: ";
for(int i=0;i<SIZE;i++)
cout<<numbers[i]<<' ';
int maxElement;
int index,counter=0;
for(maxElement=SIZE-1; maxElement>=0; maxElement--)
{
for(index=0;index<=maxElement-1;index++)
{
if(numbers[index]>numbers[index+1])
{
swap(numbers[index], numbers[index+1]);
counter++;//increments counter everytime swap occurs
}
}
}
cout<<"\nBubble Sorted: ";
for(int i=0;i<SIZE;i++)
cout<<numbers[i]<<' ';
cout<<"\nNumbers of location swap: "<<counter<<endl;
}
void swap(int &a, int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
void selectionSort(int numbers[], int SIZE)
{ cout<<"\nOriginal order: ";
for(int i=0;i<SIZE;i++)
cout<<numbers[i]<<' ';
int startScan;
int index;
int miniIndex;
int miniValue;
int counter=0;
for(startScan=0;startScan<(SIZE-1);startScan++)
{
miniIndex=startScan;
miniValue=numbers[startScan];
for(index=startScan+1;index<SIZE;index++)
{
if(numbers[index]<miniValue)
{
miniValue=numbers[index];
miniIndex=index;
}
}
swap(numbers[miniIndex], numbers[startScan]);
counter++;
}
cout<<"\nSelection Sorted: ";
for(int i=0;i<SIZE;i++)
cout<<numbers[i]<<' ';
cout<<"\nNumbers of location swap: "<<counter<<endl;
cout << endl;
}
void insertionSort(int numbers[], int SIZE, int &a, int &b)
{
int temp = a; a = b; b = temp;
int j, swap = 0;
cout<<"Original order: ";
for(int i = 0; i < SIZE; i++)
cout<< numbers[i] << ' ';
for (int i = 0; i < SIZE; i++){
j = i;
while (j > 0 && numbers[j] < numbers[j-1])
{
temp = numbers[j];
numbers[j] = numbers[j-1];
numbers[j-1] = temp;
j--; swap++;
}
}
cout <<"\nThe number of location swaps is: "<< swap << endl;
return;
}
You get 0 swaps for insertion sort because insertion sort performed 0 swaps, because the array was already sorted, because you ran bubble sort on it earlier.
You don't get 0 swaps for selection sort because your selection sort function always performs N-1 swaps, if N is the size of the array, even if the array is already sorted.
You don't get 0 swaps for bubble sort because the array isn't already sorted at that point.