incorrect data in array index - what will happen? - c++

I found a mistake I made in my code associated with indexing an array.
It compiled and I didn't notice the issue for some time. I'm curious what the index really was.
Intended code:
if(arr[i] > 3){//do stuff}
what was written:
if(arr[i > 3]){//do stuff}
what did the array index end up being?

In reality, what happens is very simple.
In the first case, the if checks each element of the array and sees if it is greater than 3.
In the second case, it's more complex than it seems. In practice, as long as the i is greater than 3, the index taken will be 1, as it satisfies the equation x > 3, otherwise I take the index 0.
In practice it is the transformation of the boolean value into an integer value. Once it takes the index, the if does nothing but be true if the value is non-zero, otherwise if the value inside the array is 0 it will be false.
A very practical example for the second problem would be:
int arr[4] = {1,2,3,4};
cout << arr[2 > 4] << endl; //The output would be 1, since 2 > 4 would be false and would return 0 as a result.
Sorry if I made a bad explanation but I tried my best :)

Related

Why didn't my alternative sorting algorithm work?

I was trying to implement a sorting code so i tried something completely without looking at any other reference codes or anything. Please tell me why my code doesnt show any output? It just runs for sometime and then stops suddenly.
I want to know where i am going wrong. I wanted to take any array as an input and sort the numbers in it in ascending order. So i just iterated throughput the array and compared adjacent elements and swaped them. Then i tried printing the numbers using their indices but it did not print anything on the screen.
#include <iostream>
using namespace std;
int main() {
int arr[6]={1,23,2,32,4,12};
int i=0;
while(i<6)
{
if(arr[i]>arr[i+1])
{
int x = arr[i];
arr[i]=arr[i+1];
arr[i+1]=x;
}
else
continue;
i++;
}
cout<<arr[0];
cout<<arr[1];
cout<<arr[2];
cout<<arr[3];
cout<<arr[4];
cout<<arr[5];
return 0;
}
I expected that the numbers will be printed in ascending order but nothing happened. And also tell me how to print an array all at once.
Thank you
Your sorting algorithm doesn't work because it performs only one pass of a variant of Bubble Sort or Insertion Sort. There has to be one more loop wrapped around your loop to repeat the operation N-1 times.
There are a number of ways to explain why multiple passes are required. Here is one explanation. Whenever we perform this step:
if (arr[i] > arr[i+1])
{
int x = arr[i];
arr[i] = arr[i+1];
arr[i+1] = x;
}
we transfer the arr[i+1] element into the arr[i] position. By doing so, we effectively skip the arr[i+1] element.
Here is what I mean. Suppose arr[i] is called x, arr[i+1] is called y and arr[i+2] is called z. We start with xyz, and exchange x and y to make yxz. But then on the next iteration of the loop, we compare x and z and have forgotten about y; x has moved forward in the array, pushing down y. Why is that a problem? Because y and z have not been compared; and those two are not necessarily in sorted order!
Suppose we have { 3, 2, 0 }. We compare 3 and 2, and swap them, giving us { 2, 3, 0}. Then we move on to comparing 3 and 0: we swap those and get { 2, 0, 3 }. See the problem? We neglected to deal with 2 and 0. That requires another pass through the array.
There is a family of algorithms which work by repeatedly scanning through an array and exchanging items. I suggest studying the following of the common algorithms in this family: insertion sort, selection sort and Shell sort. Also look at bubble sort, in order to understand why it's a poor algorithm compared to either insertion or selection sort that it is closely related to.
your loop condition is incorrect - the last iteration will compare arr[5] and arr[6] which gives index out of bound.
you update your iterator "i" only if you swap, so if your loop encounters the case where arr[i] <= arr[i+1], your iterator will never get updated and your program will run infinitely.
your algorithm implements just a first iteration of bubble sort i.e. it bubbles up (from left to right) the largest number and stops. so the final array looks like [1, 2, 23, 4, 12, 32]

Is this code a bubble sorting program?

I made a simple bubble sorting program, the code works but I do not know if its correct.
What I understand about the bubble sorting algorithm is that it checks an element and the other element beside it.
#include <iostream>
#include <array>
using namespace std;
int main()
{
int a, b, c, d, e, smaller = 0,bigger = 0;
cin >> a >> b >> c >> d >> e;
int test1[5] = { a,b,c,d,e };
for (int test2 = 0; test2 != 5; ++test2)
{
for (int cntr1 = 0, cntr2 = 1; cntr2 != 5; ++cntr1,++cntr2)
{
if (test1[cntr1] > test1[cntr2]) /*if first is bigger than second*/{
bigger = test1[cntr1];
smaller = test1[cntr2];
test1[cntr1] = smaller;
test1[cntr2] = bigger;
}
}
}
for (auto test69 : test1)
{
cout << test69 << endl;
}
system("pause");
}
It is a bubblesort implementation. It just is a very basic one.
Two improvements:
the outerloop iteration may be one shorter each time since you're guaranteed that the last element of the previous iteration will be the largest.
when no swap is done during an iteration, you're finished. (which is part of the definition of bubblesort in wikipedia)
Some comments:
use better variable names (test2?)
use the size of the container or the range, don't hardcode 5.
using std::swap() to swap variables leads to simpler code.
Here is a more generic example using (random access) iterators with my suggested improvements and comments and here with the improvement proposed by Yves Daoust (iterate up to last swap) with debug-prints
The correctness of your algorithm can be explained as follows.
In the first pass (inner loop), the comparison T[i] > T[i+1] with a possible swap makes sure that the largest of T[i], T[i+1] is on the right. Repeating for all pairs from left to right makes sure that in the end T[N-1] holds the largest element. (The fact that the array is only modified by swaps ensures that no element is lost or duplicated.)
In the second pass, by the same reasoning, the largest of the N-1 first elements goes to T[N-2], and it stays there because T[N-1] is larger.
More generally, in the Kth pass, the largest of the N-K+1 first element goes to T[N-K], stays there, and the next elements are left unchanged (because they are already increasing).
Thus, after N passes, all elements are in place.
This hints a simple optimization: all elements following the last swap in a pass are in place (otherwise the swap wouldn't be the last). So you can record the position of the last swap and perform the next pass up to that location only.
Though this change doesn't seem to improve a lot, it can reduce the number of passes. Indeed by this procedure, the number of passes equals the largest displacement, i.e. the number of steps an element has to take to get to its proper place (elements too much on the right only move one position at a time).
In some configurations, this number can be small. For instance, sorting an already sorted array takes a single pass, and sorting an array with all elements swapped in pairs takes two. This is an improvement from O(N²) to O(N) !
Yes. Your code works just like Bubble Sort.
Input: 3 5 1 8 2
Output after each iteration:
3 1 5 2 8
1 3 2 5 8
1 2 3 5 8
1 2 3 5 8
1 2 3 5 8
1 2 3 5 8
Actually, in the inner loop, we don't need to go till the end of the array from the second iteration onwards because the heaviest element of the previous iteration is already at the last. But that doesn't better the time complexity much. So, you are good to go..
Small Informal Proof:
The idea behind your sorting algorithm is that you go though the array of values (left to right). Let's call it a pass. During the pass pairs of values are checked and swapped to be in correct order (higher right).
During first pass the maximum value will be reached. When reached, the max will be higher then value next to it, so they will be swapped. This means that max will become part of next pair in the pass. This repeats until pass is completed and max moves to the right end of the array.
During second pass the same is true for the second highest value in the array. Only difference is it will not be swapped with the max at the end. Now two most right values are correctly set.
In every next pass one value will be sorted out to the right.
There are N values and N passes. This means that after N passes all N values will be sorted like:
{kth largest, (k-1)th largest,...... 2nd largest, largest}
No it isn't. It is worse. There is no point whatsoever in the variable cntr1. You should be using test1 here, and you should be referring to one of the many canonical implementations of bubblesort rather than trying to make it up for yourself.

Having trouble reading the output of my code

So the question was to return the difference between the maximum number and the smallest. My first code written was.
public int bigDiff(int[] nums) {
int max = 0;
int min = 0;
for(int i = 0; i < nums.length; i++){
if(Math.max(max, nums[i]) == nums[i])
max = nums[i];
else if (Math.min(min, nums[i]) == nums[i])
min = nums[i];
}
return max-min;
}
but this only outputs the largest number in the list.
Although, when I was just playing around and changed
int max = nums[0];
int min = nums[0];
it worked?, but I have no idea why. If anyone could understand how I would appreciate an explanation :D
Imagine array of values: 1,2,3. The proper minumum is 1. But, you have initialized min to 0. No value from this array is less than 0, so, min remains 0. Whoops, the answer is wrong. The similar case: array of -1, -2, -3, and maximum inited to 0 - again, wrong result.
I know three standard approaches to fix this:
Maximum and minimum are inited to the first value of sequence (array, in your case). That is exactly how you fixed it - by setting to nums[0]. OTOH you needn't start with index 0 - 1 is good also (very minor optimization but worth noting).
Maximum is inited with a smallest value ever possible for this type (for int, it's INT_MIN from <limits.h>), and minumum - to possible maximal one (INT_MAX, respectively). Most likely both will be immediately updated with nums[0].
A boolean variable with meaning "no values yet" is tested, and direct assignment instead of comparing is used when it is set (in your case, with i == 0 and immediately reset to false. It's a definitely overkill for a directly available integer array, but is good for cumbersome situations when comparing is inside of a callback instantiated through a template calling sequence, or another too-many-abstraction-levels design...
You have already warned that else is wrong, but, mathematically, it's allowed for my variants 1 and 3 (but not for variant 2! let you find out the fail proof by itself).
When you was just playing around and changed int max = nums[0]; int min = nums[0]; it worked.
Because, if you want to get the max num, you have to let variable max smaller than all of the member of arrary, then the function max() will make the max be the current maximum number。
So,the variable min must be larger then each member of the array!

Why is my for loop crashing on a vector of doubles?

This for loop always crashes immediately:
for (auto i = v.size() - 1; i >=0; --i);
Obviously I have a whole load of code in the loop, and v is a vector of doubles. I'm trying to iterate over them in reverse order.
What is going on here?
for (auto i = v.size() - 1; i >=0; --i);
Look at vector::size() method - it returns usually unsigned int (on strange platforms it might be other unsigned type)! So your i variable will have unsigned type.
When your loop will come to step i == 0 it will decrement it and i will have value 2^32 - 1 == UNSIGNED_INT_MAX (or other positive value if you work on strange platform - see vector::size_type on your platform to see underlying type). So it will never be less then 0, it will never stop your loop. I guess when it turns so big it crashes becouse it goes out of range, but i don't see whole code to be sure.
See here - look for size_type typedef - it says its unsigned type.
You might want to use reverse iterators (see #NathanOliver's response), though i'm not very fond of them in simple loops.
Since i is unsigned it will never be less than 0. It will wrap around to the maximum value that it can hold instead.
If you want to iterate through a vector backwards then you should use a reverse_iterator
std::vector<int> foo = {1,2,3,4,5,6,7,8,9};
for (auto it = foo.rbegin(); it != foo.rend(); ++it)
std::cout << *it << " ";
This will output
9 8 7 6 5 4 3 2 1
The variable i will be an unsigned type.
That can never be less than zero.
Eventually you will access an element outside the vector as i will wrap around to the largest possible unsigned value rather than going negative
What Bathsheba said: the auto type is an unsigned. So decrementing 0 becomes some large positive number, which is >= 0 so the loop continues, but that value is outside the vector's range and causes the crash.

find a single element in an array of consecutive duplicate elements

Given an array of elements where every element is repeated except a single element. Moreover all the repeated elements are consecutive to each other.
We need to find out the index of that single element.
Note:
array may not be sorted
expected time O(logn)
range of elements can
be anything.
O(n) is trivial. but how can I figure out logn?
Gave a thought to bitwise operators also but nothing worked out.
Also, I am unable to make use of this statement in this question all the repeated elements are consecutive to each other.
Ex: 2 2 3 3 9 9 1 1 5 6 6
output 5
It can be done in O(logn) by checking if arr[2k] == arr[2k+1], k>=0 - if it is, then the distinct elementt is AFTER 2k+1, if it's not - than it is before before 2k+1.
This allows you to effectively trim half of the array at each step by checking the middle value, and recursing only on a problem half as big, getting it O(logn) overall.
Python code:
def findUnique(arr,l,r):
if r-l < 2:
return (arr[l],l)
mid = (r-l)/2 + l
if mid % 2 != 0:
flag = -1
else:
flag = 0
if (mid == 0 or arr[mid-1] != arr[mid] ) and (mid == len(arr)-1 or arr[mid] != arr[mid+1] ):
return (arr[mid],mid)
if arr[mid+flag] == arr[mid+1+flag]:
return findUnique(arr,mid,r)
return findUnique(arr,l,mid)
Assuming each element is repeated exactly twice, except one, then it is easy.
The first answer is correct, just feel like I could elaborate a bit on it.
So, lets take your example array.
a = [2 2 3 3 9 9 1 1 5 6 6];
If all elements were paired, then you can take an even index and know for sure that the next element will be the same.
a[0] = 2;
a[1] = 2; //as well
a[2] = 3;
a[3] = 3; //as well
General case:
a[k] = a[k+1] = x;
where k is even, and x is some value.
BUT, in your case, we know that there is one index that doesn't follow this rule.
in order to find it, we can use Binary Search (just for reference), with a bit of extra computation in the middle.
We go somewhere in the middle, and grab an element with an even index.
If that elements' value equals to the next elements' value, then your lonely value is in the second part of the array, because the pairing wasn't broken yet.
If those values are not equal, then either your lonely value is in the first half OR you are at it (it is in the middle).
You will need to check couple elements before and after to make sure.
By cutting your array in half with each iteration, you will achieve O(logn) time.