Counter in arrays c++ - c++

i have a really simple code right there that counts how much values you need in arrays.
for (int i = 0; i < dm; i++)
{
if (arr[i] == c)
{
counter++;
}
};
But i need to make it a little bit tricky.I need to count number of same values. Imagine i have an array {4,4,4,3,3,2,2,1,1,0,0,0} and i need to find how much "twins" there. So 3,2,1 are twins because they have only 1 exact friend.
I tried something like 2 fors and 2 counters but still have troubles. Thanks. Hope you understand what i mean by "twin". x and x are twins and y,y,y are not ( just in case)

I'd make a map that counts - for each individual number in the array - their occurrences. The code could look as follows:
#include <iostream>
#include <map>
int main()
{
const int numberOfElements = 12;
int array[numberOfElements] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
std::map<int,int> counts;
for (int i=0; i < numberOfElements; i++) {
counts[array[i]]++;
}
for (auto x : counts) {
if (x.second == 2) {
cout << "pair: " << x.first << endl;
}
}
return 0;
}
If - for some reason - the range of the elements is limited, you could also use a "plain" array for counting the occurrences. If, for example, the elements are in the range of 0..4, you could use the following fragment:
const int numberOfElements = 12;
const int elementMax = 4;
int array[numberOfElements] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
int counts[elementMax+1] = {};
for (int i=0; i<numberOfElements; i++) {
counts[array[i]]++;
}
for (int i=0; i <= elementMax; i++) {
if (counts[i] == 2) {
cout << "pair: " << i << endl;
}
}
And if your array is sorted, than a solution without a counter-array could look as follows:
const int numberOfElements = 12;
int array[numberOfElements] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
int prev = -1;
int count = 0;
for (int i=0; i<numberOfElements; i++) {
if (array[i] == prev) {
count++;
}
else {
if (count == 2) {
cout << "pair: " << prev << endl;
}
count=1;
prev = array[i];
}
}
if (prev >= 0 && count==2) {
cout << "pair: " << prev << endl;
}

You can do that in one pass and use binary search for efficiency:
int arr[] = { 4,4,4,3,3,2,2,1,1,0,0,0 };
int twins = 0;
for( auto i = std::begin( arr ); i != std::end( arr ); ) {
auto next = std::upper_bound( i, std::end( arr ), *i, std::greater<int>() );
if( std::distance( i, next ) == 2 ) ++twins;
i = next;
}
Live example
In case there are not too many duplicates in the array std::upper_bound could be not efficient and can be easily replaced:
auto next = std::find_if( std::next( i ), std::end( arr ), [i]( int n ) { return *i != n; } );

Solution without using additional array:
int twins_counter = 0;
for (int i = 0; i < dm; i++)
{
int counter = 0; // counter for elements
for (int j = 0; j < dm; j++)
{
if (arr[i] == arr[j])
{
if( j < i )
{
break; // we have searched twin for this element already
}
counter++;
if( counter > 2 )
{
break; // we meet element third time, it isn't twin
}
}
}
if( counter == 2 )
{
twins_counter++;
}
};
For sorted (upwards or downwards) arrays one cycle is enough:
int twins_counter = 0;
int counter = 1;
for (int i = 1; i < dm; i++)
{
if( arr[i] == arr[i-1] )
{
counter++;
}
else
{
if( counter == 2 )
{
twins_counter++;
counter = 1;
}
}
}
// check last value
if( counter == 2 )
{
twins_counter++;
}

Related

Find similar numbers - array inconsistency

I'm trying to solve a simple beginner exercise, I compare two arrays and find the numbers that appear in both. The result is put into another array called result. For whatever reason the result should contain "2 44 55" but it shows "2 1 10 10". What did I do wrong?
#include <iostream>
void common_elements(int array_1[], int array_2[]){
int result[] {0};
int counter{0};
for (int i{0}; i < 10; i++){
for (int j{0}; j < 10; j++){
if (array_2[i] == array_1[j]){
result[counter] = array_1[j];
counter++;
}
}
}
if (counter == 0) {
std::cout << "There are 0 common elements";
} else {
std::cout << "There are " << counter << " common elements they are : ";
for (int k{0}; k < counter; k++){
std::cout << result[k] << " ";
}
}
}
int main(){
int data1[] {1,2,4,5,9,3,6,7,44,55};
int data2[] {11,2,44,45,49,43,46,47,55,88};
common_elements(data1,data2);
return 0;
}
I'm confused because when I std::cout the numbers during examination (two nested loops), the result is correct.
It is just containing one single element, because the compiler deduces the length to 1. This would mean the 2 is valid, all other values are "out of bound". Thanks for your help. I repaired it to
int result[10]{0};
Now it's working, thanks a lot.
Btw: It is a C++ course but it starts from the very beginning. That why this looks like C.
For starters the function should be declared at least like
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 );
Using the magic number 10 within the function as
for (int i{0}; i < 10; i++){
does not make sense. The function can be called for arrays that have different numbers of elements.
This declaration of an array
int result[] {0};
declares an array with only one element that also does not make sense.
Also the function should not output any message. It is the caller of the function that decides whether to output a message. The function should return a sequence of common elements of two arrays.
The function can be defined the following way
#include <vector>
#include <iterator>
#include <functional>
//...
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 )
{
std::vector<int> v;
if ( n1 != 0 && n2 != 0 )
{
if ( n2 < n1 )
{
std::swap( n1, n2 );
std::swap( array_1, array_2 );
}
for ( size_t i = 0; i < n1; i++ )
{
size_t count = 1;
for ( size_t j = 0; j < i; j++ )
{
if ( array_1[j] == array_1[i] ) ++count;
}
for ( size_t j = 0; count != 0 && j < n2; j++ )
{
if ( array_2[j] == array_1[i] )
{
--count;
}
}
if ( count == 0 ) v.push_back( array_1[i] );
}
}
return v;
}
And in main the function is called like
int data1[] {1,2,4,5,9,3,6,7,44,55};
int data2[] {11,2,44,45,49,43,46,47,55,88};
auto v = common_elements( data1, std::size( data1 ), data2, std::size( data2 ) );
if ( std::size( v ) == 0 )
{
std::cout << "There are 0 common elements";
}
else
{
std::cout << "There are " << std::size( v ) << " common elements they are : ";
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
Instead of the vector you could use std::map<intg, size_t>. In this case the container will contain how many times a common number is encountered in the both arrays.
Here is a demonstration program.
#include <iostream>
#include <vector>
#include <iterator>
#include <functional>
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 )
{
std::vector<int> v;
if (n1 != 0 && n2 != 0)
{
if (n2 < n1)
{
std::swap( n1, n2 );
std::swap( array_1, array_2 );
}
for (size_t i = 0; i < n1; i++)
{
size_t count = 1;
for (size_t j = 0; j < i; j++)
{
if (array_1[j] == array_1[i]) ++count;
}
for (size_t j = 0; count != 0 && j < n2; j++)
{
if (array_2[j] == array_1[i])
{
--count;
}
}
if (count == 0) v.push_back( array_1[i] );
}
}
return v;
}
int main()
{
int data1[]{ 1,2,4,5,9,3,6,7,44,55 };
int data2[]{ 11,2,44,45,49,43,46,47,55,88 };
auto v = common_elements( data1, std::size( data1 ), data2, std::size( data2 ) );
if (std::size( v ) == 0)
{
std::cout << "There are 0 common elements";
}
else
{
std::cout << "There are " << std::size( v ) << " common elements they are : ";
for (const auto &item : v)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
}
The program output is
There are 3 common elements they are : 2 44 55

Why am I not able to push a pair after a limit in the vector?

The problem is to find if a given sequence of numbers can form a valid permutation or not. The problem statement is trivial for the real problem. So, I am pushing a pair of integers into the vector. The first part being the number itself and second being 0 or 1.
The code works fine till a sequence 1041 long (specific after debugging a lot). Just to debug I added a print statement after pushing each pair inside the vector. For a length of 1042, the code shows pushed 1040 and then pushed 1 (which is weird) and then just hangs on there.
I am attaching the code as well as the input and terminal output.
You can just check the main function
Code
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
using namespace std;
bool comparator_function(pair<int, int> a, pair<int, int> b) {
return (a.first < b.first);
}
//index_added -> the index at which the latest element was added
void set_r_array(int* r_array_ref, int* per_array_ref, int size, int* count, int index_added) {
for(int i = 1;i <= size; i++) {
count[i] = 0;
}
int temp = index_added;
while(index_added <= size) {
if(index_added == size) {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = size;
break;
}
else {
r_array_ref[temp] = -1;
break;
}
}
else {
if(per_array_ref[index_added] == 0) {
r_array_ref[temp] = index_added;
break;
}
else {
index_added++;
}
}
}
for(int i = 1;i <= size; i++) {
if(r_array_ref[i] != -1) {
count[r_array_ref[i]]++;
}
}
}
bool check_max(int* count, int next_element, int size) {
int max_count = -1, index = 0;
for(int i = 1;i <= size; i++) {
int temp_val = count[i];
if(max_count <= temp_val) {
max_count = temp_val;
index = i;
}
}
int num = 0;
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
num++;
}
}
//one max
if(num == 1) {
if(next_element == index) {
return true;
}
return false;
}
else {
for(int i = 1;i <= size; i++) {
if(count[i] == max_count) {
if(next_element == i) {
return true;
}
}
}
return false;
}
}
int main() {
int testCases;
cin >> testCases;
cin.ignore();
while(testCases-- > 0) {
int n, result_flag = 0;
cin >> n;
cin.ignore();
vector<pair<int, int>> per;
int temp;
for(int i = 0;i < n; i++) {
cin >> temp;
pair<int, int> temp_pair = make_pair(temp, i+1);
per.push_back(temp_pair);
//debug statement
cout << "pushed " << temp << endl;
}
auto start = std::chrono::high_resolution_clock::now();
cout << "start" << endl;
sort(per.begin(), per.end(), comparator_function);
int permutation_array[n+1], r_array[n+1], count[n+1];
for(int i = 0;i <= n; i++) {
permutation_array[i] = 0;
r_array[i] = i;
count[i] = 1;
}
cout << "end" << endl;
permutation_array[per[0].second] = per[0].first;
set_r_array(r_array, permutation_array, n, count, per[0].second);
//insertion of numbers
for(int i = 1;i < n; i++) {
//check if the next element inserted has the largest count rn or not
int next_element = per[i].second;
if(!check_max(count, next_element, n)) {
cout << "No" << endl;
result_flag = -1;
break;
}
permutation_array[per[i].second] = per[i].first;
set_r_array(r_array, permutation_array, n, count, per[i].second);
}
if(result_flag == 0) {
cout << "Yes" << endl;
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
cout << "Time: " << duration.count() << " microseconds" << endl;
}
}
Input 1
1
5
2 3 4 5 1
Output 1
pushed 2
pushed 3
pushed 4
pushed 5
pushed 1
start
end
Yes
Input 2
1
1042
1 2 3 4 ... so on till 1042
Output 2
pushed 1
pushed 2
.
.
.
pushed 1040
pushed 1
and then hangs, from here on
The complexity of the code is O(n^2). So, I don't think it has to do anything with that. Since the input can be at max 10^4 order. Moreover, according to the print debugging, I think the issue is with the input.
You have issue with input as you reach console line limit.
Put your input into a file should solve that issue.
Then you should be able to debug your algorithm which seems more complicated than needed.

Having Difficulty With This Q: Allow User To Input Values of Array and Do So With For, While loops, also output the largest number entered

I have to create a function which uses a for loop or while loop and an array, to display the largest number out of a group of numbers, and I'm having trouble with the question in the title.
When I run this code, it's not allowing the user to input however many elements in the array he wants, and it does not stop when the user wants to stop by entering a letter like g for ex. It also doesn't output the largest number at the end of what the user wants entered in the array.
What exactly is wrong with my code?
#include <iostream>
using namespace std;
void printarray(int array[], int size)
{
for (int i = 0; i < size; i++)
{
cout << array[i] << endl;
}
return;
}
int main()
{
const int SIZE = 2000;
int count = 0;
int userinput[SIZE];
int largest = 0;
for (int i = 0; i < SIZE; i++)
{
if (cin >> userinput[i])
{
count++;
}
else
{
break;
}
while (count < userinput[i])
{
if (largest < userinput[i])
{
largest = userinput[i];
}
count++;
}}
printarray(userinput, count);
cin.clear();
cin.ignore();
return 0;
}
The problem of the code is its bad indentation.
for (int i = 0; i < SIZE; i++)
{
if (cin >> userinput[i])
{
count++;
}
else
{
break;
}
while (count < userinput[i])
{
if (largest < userinput[i])
{
largest = userinput[i];
}
count++;
}}
The while loop is inside the for loop. And this condition of the while loop
count < userinput[i]
does not make sense.
Separate the loops.
for ( size_t i = 0; i < SIZE; i++ )
{
if (cin >> userinput[i])
{
count++;
}
else
{
break;
}
}
int largest = count == 0 ? 0 : userinput[0];
for ( size_t i = 1; i < count; i++ )
{
if ( largest < userinput[i] )
{
largest = userinput[i];
}
}
Take into account that you could use the standard algorithm std::max_element declared in the header <algorithm>
For example
auto it = std::max_element( userinput, userinput + count );
if ( it != userinput + count ) largest = *it;
The function printarray can be declared and defined like
std::ostream & printarray( const int array[], size_t size, std::ostream &os = std::cout )
{
for ( size_t i = 0; i < size; i++ )
{
os << array[i] << ' ';
}
return os;
}
Pay attention to that nowhere in your program the largest element is outputted.

C++ : Creating a mathematical set to compute subset checking

I would like to know how to check for subset and proper subset of two arrays. I cannot figure out a logical way to check for the subset of two arrays. Here is what I have so far.
Here is my Code:
Sets.h
#ifndef SETS_H
#define SETS_H
using namespace std;
class Sets{
private:
static const int SIZE = 5;
int arr[SIZE];
public:
Sets();
void addElement(int);
int getElement(int);
int getSize();
bool isSubset(Sets);
bool isProper(Sets);
void printSet();
void printOrderedPairs(Sets);
};
#endif
Sets.cpp
#include "Sets.h"
#include <iostream>
using namespace std;
Sets::Sets(){
for (int i = 0; i < SIZE; i++){
arr[i] = -1;
}
}
int Sets::getSize(){
return SIZE;
}
void Sets::addElement(int l){
for (int i = 0; i < SIZE; i++){
if (arr[i] == -1){
arr[i] = l;
break;
}
}
}
int Sets::getElement(int j){
if (j < SIZE){
return (-1);
}
else{
int temp;
temp = arr[j];
return temp;
}
}
bool Sets::isSubset(Sets b){
for (int i = 0; i < SIZE; i++){
for (int j = 0; j < SIZE; j++){
if (arr[i] != b.arr[i]){
return false;
}
}
}
return true;
}
bool Sets::isProper(Sets b){
for (int i = 0; i < SIZE; i++){
for (int j = 0; j < SIZE; j++){
if (arr[i] != b.arr[j]){
return false;
}
}
}
return true;
}
void Sets::printOrderedPairs(Sets b){
cout << "A X B = {";
for (int i = 0; i < SIZE-1; i++){
for (int j = 0; j < SIZE; j++){
cout << "(" << arr[i] << "," << b.arr[j] << ") , ";
}
}
cout << "}";
}
void Sets::printSet(){
cout << "{";
for (int i = 0; i < SIZE; i++){
cout << arr[i] << " ,";
}
cout << "}";
}
TestSets.cpp
#include <iostream>
#include "Sets.h"
using namespace std;
int main(){
Sets a;
Sets b;
a.addElement(1);
a.addElement(3);
a.addElement(5);
a.addElement(7);
a.addElement(9);
b.addElement(1);
b.addElement(3);
b.addElement(5);
b.addElement(7);
b.addElement(9);
cout << "Set A is ";
a.printSet();
cout << endl;
cout << "Set B is ";
b.printSet();
cout << "\n" << endl;
a.printOrderedPairs(b);
cout << "\n" << endl;
if (a.isSubset(b) == true){
cout << "Set B is subset of set A" << endl;
}
else{
cout << "Set B is not a subset of set A" << endl;
}
if (a.isProper(b) == true){
cout << "Set B is proper subset of set A" << endl;
}
else{
cout << "Set B is not a proper subset of set A" << endl;
}
system("PAUSE");
return 0;
}
Any help would be appreciate at this point. Thanks in advance.
A way to check is a set b is a subset of another set a is to loop through each element of b and verify that it is present in a. This is faster if both the sets are sorted (and that's the case of std::set for example).
Your class uses an array of int (and it would be better using a std::vector instead) of fixed size (5, for whatever reason). I think it should be an improvment using some dynamical allocation instead.
So, to check if a set is a subset I'll suggest you something like:
// a.isSubset(b) check if b is a subset of a
bool Sets::isSubset( const Sets &b ) {
for (int i = 0; i < b.size; i++ ) {
bool is_present = false;
for (int j = 0; j < size; j++ ) {
// b is a subset if all of its element are in a
// so check if any element of b is in a
if ( arr[j] == b.arr[i] ) {
is_present = true;
break;
}
}
if ( !is_present ) return false;
}
return true;
}
// a.isProper(b) check if b is a proper subset of a
bool Sets::isProper( const Sets &b) {
int n_equals = 0;
for (int i = 0; i < b.size; i++) {
bool is_present = false;
for (int j = 0; j < size; j++) {
// b is a prpoper subset if all of its element are in a
// but there exists at least one element of a that is not in b
if ( arr[j] == b.arr[i] ) {
is_present = true;
++n_equals;
break;
}
}
if ( !is_present ) return false;
}
return n_equals < size;
}
Your class should be modified accordingly.
EDIT
To gain better performances and to simplify most of the algorithms it's better to use a sorted container. For example, the two function belove may become:
// a.isSubset(b) check if b is a subset of a. Requires that both are sorted
bool Sets::isSubset( const Sets &b ) {
for (int i = 0, j = 0; i < b.size; i++ ) {
// scan a, which is sorted
while ( j < size && arr[j] < b.arr[i] ) ++j;
if ( j == size || arr[j] > b.arr[i] )
// There's at least one element of b which not belongs to a
return false;
// b.arr[i] == arr[j], move on
}
// all the element of b are in a too
return true;
}
// a.isProper(b) check if b is a proper subset of a.
// It requires that both are sorted
bool Sets::isProper( const Sets &b ) {
int n_equals = 0;
for (int i = 0, j = 0; i < b.size; i++ ) {
while ( j < size && arr[j] < b.arr[i] ) ++j;
if ( j == size || arr[j] > b.arr[i] )
// b is a prpoper subset if all of its element are in a
// but there exists at least one element of a that is not in b
return false;
++n_equals;
}
return n_equals < size;
}
To force the sorting you only have to modify the function that adds elements. I added some helper functions too:
#include <iostream>
using namespace std;
class Sets{
private:
int size;
int allocated;
int *arr;
// It's way better using a std::vector:
// vector<int> v;
// or you can cheat and use a std::set
public:
Sets();
~Sets();
void addElement(int);
void delElement(int);
int getLowerPos(int);
int getElement(int);
int getSize();
bool doesContain(int);
bool isSubset(const Sets &);
bool isProper(const Sets &);
void printSet();
void printOrderedPairs(const Sets &);
};
Sets::Sets() : size(0), allocated(0), arr(nullptr) { }
Sets::~Sets() {
delete[] arr;
}
int Sets::getSize(){
return size;
}
// Add an element if it isn't already present, keeping the array sorted
void Sets::addElement( int x ) {
int pos = this->getLowerPos(x);
if ( pos < size && arr[pos] == x ) return;
if ( size == allocated ) {
// it's time to expand the array. If it's empty, start from 8
allocated = allocated > 0 ? allocated * 2 : 8;
int *new_arr = new int[allocated];
for ( int i = 0; i < pos; i++ ) {
new_arr[i] = arr[i];
}
for ( int i = size; i > pos; --i ) {
new_arr[i] = arr[i - 1];
}
delete[] arr;
arr = new_arr;
}
else {
for ( int i = size; i > pos; --i ) {
arr[i] = arr[i - 1];
}
}
arr[pos] = x;
++size;
}
// Remove an element from the set if it is present, keeping the array sorted
void Sets::delElement( int x ) {
int pos = this->getLowerPos(x);
if ( pos == size || arr[pos] != x ) return;
// I move the elements and update size only, without deallocation.
--size;
for ( int i = pos; i < size; ++i ) {
arr[i] = arr[i + 1];
}
}
// I guess you want to return the element j of the set or -1 if it's not present
int Sets::getElement( int j ){
// consider using size_t instead of int for indeces or at least unsigned int
if ( j < 0 || j >= size )
// I assume all the elements are positive integers
return -1;
else
// why the temp?
return arr[j];
}
// Find the position of the lowest element in the set such that x <= arr[pos]
// with a binary search. It requires that the array is sorted.
// Return the value size if all the elements are lower then x
int Sets::getLowerPos( int x ) {
int first = 0, count = size - first, step, pos = 0;
while ( count > 0 ) {
step = count / 2;
pos = first + step;
if ( arr[pos] < x ) {
first = ++pos;
count -= step + 1;
}
else
count = step;
}
return first;
}
// Check if x is present in the set with a binary search.
// It requires that the array is sorted
bool Sets::doesContain( int x ) {
int pos = this->getLowerPos(x);
return ( pos != size && arr[pos] == x );
/*
// Or directly with a simple binary search:
int low = 0, high = size - 1, pos;
while ( low <= high ) {
pos = low + (high - low) / 2;
if ( x == arr[pos] )
return true;
else if ( x < arr[pos] )
high = pos - 1;
else
low = pos + 1;
}
return false;
*/
}
// ... isSubset() and isProper() as above ...
void Sets::printOrderedPairs( const Sets &b){
cout << "A X B = {";
for (int i = 0; i < size; i++){
for (int j = 0; j < b.size; j++){
cout << '(' << arr[i] << ", " << b.arr[j] << "), ";
}
}
cout << "\b\b} ";
}
void Sets::printSet(){
cout << '{';
for (int i = 0; i < size; i++){
cout << arr[i] << ", ";
}
cout << "\b\b} ";
}
int main(void) {
try {
Sets a;
Sets b;
a.addElement(9);
a.addElement(3);
a.addElement(7);
a.addElement(5);
a.addElement(1);
b.addElement(3);
b.addElement(7);
b.addElement(1);
b.addElement(5);
cout << "Set A is ";
a.printSet();
cout << "\nSet B is ";
b.printSet();
cout << "\n\n";
a.printOrderedPairs(b);
cout << "\n\n";
if ( a.isSubset(b) ) {
cout << "Set B is a subset of set A\n";
}
else {
cout << "Set B is not a subset of set A\n";
}
if ( a.isProper(b) ){
cout << "Set B is a proper subset of set A\n";
}
else{
cout << "Set B is not a proper subset of set A\n";
}
system("PAUSE");
}
catch ( const bad_alloc& e) {
cout << "Allocation failed: " << e.what() << '\n';
}
return 0;
}
Now the output is:
Set A is {1, 3, 5, 7, 9}
Set B is {1, 3, 5, 7}
A X B = {(1, 1), (1, 3), (1, 5), (1, 7), (3, 1), (3, 3), (3, 5), (3, 7), (5, 1), (5, 3), (5, 5), (5, 7), (7, 1), (7, 3), (7, 5), (7, 7), (9, 1), (9, 3), (9, 5), (9, 7)}
Set B is subset of set A
Set B is proper subset of set A

Problems with binary search function

Having trouble with the binary_search function listed at the top. not sure where to go with it. I'm not very familiar with binary searching.
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
void get_input(ifstream& fin, int a[], int size, int & array_size);
void binary_search (int a[], int & array_size)
{
cout << "Please enter the element you would like to search for \n";
int element;
cin >> element;
int lastindex=array_size-1, startindex=0;
while (startindex <= lastindex)
{
int midindex=(array_size/2);
if(element > a[midindex])
{
startindex=midindex;
}
else if (element < a[midindex])
{
lastindex=midindex-1;
}
}
}
int main()
{
int array_size=-1;
int a[100];
ifstream fin;
get_input (fin, a, 100, array_size);
binary_search (a, array_size);
return 0;
}
void get_input (ifstream& fin, int a[], int size, int & array_size)
{
fin.open("numbers.txt");
if (fin.fail())
{
cout << "File failed to open";
exit(1);
}
for(int i = 0; i < size; i++)
{
a[i] = 0;
}
cout << "The numbers in the array are: \n\n";
for (int i = 0; i < size; i++)
{
if (!fin.eof())
{
fin >> a[i];
array_size ++;
}
}
for (int i = 0; i < array_size; i++)
{
cout << a[i] << " ";
}
cout << "\n\n\n";
cout << "The numbers in the array sorted are: \n\n";
for(int i = 0; i < array_size; ++i )
{
int temp2 = a[i];
for (int j = i+1; j < array_size; ++j )
{
if( a[j] < temp2)
{
temp2 = a[j];
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
for (int i = 0; i < array_size; i++)
{
cout << a[i] << " ";
}
cout << "\n\n\n";
fin.close();
}
when done the program is suppose to take an input from a file assign it to an array then sort the array. After this i need to use a binary search to find a number given by the user and display its place in the array to the user.
update: getting wrong output for the index found.... should i just add one to midindex?
void binary_search (int a[], int & array_size)
{
cout << "Please enter the element you would like to search for \n";
int element;
cin >> element;
int lastindex=array_size-1, startindex=0;
while (startindex <= lastindex)
{
int midindex= startindex + (lastindex - startindex) / 2;
if(element > a[midindex])
{
startindex=midindex+1;
}
else if (element < a[midindex])
{
lastindex=midindex-1;
}
else if (element == a[midindex])
{
cout<<"Element "<<element<<" found at index "<<midindex<<endl;
return;
}
}
}
Try changing
startindex=midindex;
to:
startindex=midindex + 1;
and
int midindex=(array_size/2);
to
int midindex= startindex + (lastindex - startindex) / 2
and most importantly you are doing nothing when you find the element !!
if(element == a[midindex]) {
cout<<"Element "<<element<<" found at index "<<midindex<<endl;
return;
}
My first reaction is to change the line
int midindex=(array_size/2);
to
int midindex = startindex + (lastindex - startindex) / 2;
Also, don't you want to report if the sought element was found or not? To detect the case when the element is found, another if branch like the following
if( element == a[midindex] )
can be inserted. That can have a return element; or return midindex inside it coupled with a return failure; outside the loop.
EDIT: I made a casual attempt to write a version of binary search. I don't claim it to be correct, as binary search is (in)famous for getting incorrect. Some code with test cases and output is uploaded at codepad.
Snippet:
int *
mybsearch( int const * const a, size_t const n, int const key ) {
int * lo = const_cast< int * >( a );
int * hi = lo + n;
while( lo <= hi ) {
int * const mid = lo + (hi - lo) / 2;
int const midelem = *mid;
if( key == midelem ) {
return mid;
}
else if( key < midelem ) {
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return NULL;
}
The main and test code:
int main() {
int const arr[] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
size_t const num = sizeof( arr ) / sizeof( int );
int * pos20 = mybsearch( arr, num, 20 );
assert( pos20 && (*pos20 == 20) );
int * pos25 = mybsearch( arr, num, 25 );
assert( !pos25 );
int * pos5 = mybsearch( arr, num, 5 );
assert( !pos5 );
int * pos105 = mybsearch( arr, num, 105 );
assert( !pos105 );
}
Binary search works nicely as a recursive algorithm. Pass in the array and length, check the middle value, and recurse on the upper / lower half of the array, as appropriate.
Consider carefully what is not right about int midindex=(array_size/2); when array_size = 1. Then generalize to array_size = 3. Then to any odd number. This will require small run simulations in your head or on paper.
You're close. You want to do something like this:
int binary_search ...
so you can return the index of the element
while (startindex < lastindex)
{
int midindex=(startindex+endindex)/2;
if(element = a[midindex]) {
return midindex;
}
else if(element > a[midindex])
{
startindex=midindex+1;