C++ Binary search algorithm to work like lower_bound - c++

I do have another question following my previous -
I am creating a version of lower_bound with something like binary search. With the BinarySearch function I find a place where to insert the new item and with the for cycle I do move the rest of the array and insert the right item so I can insert it to the right position.
But the following BinarySearch function does not work properly.
Can anyone see why?
bool CReg::AddCar ( const char *name){
CArr * tmp = new CArr(name); // an item I am going to insert
int pos = BinarySearch(name,0,len); //len = number of items in array
checkLen(); // whether I do have enough space to move the array right
if (length!=0)
for (int i = m_len; i>=pos; i-- )
Arr[i+1] = spzArr[i];
Arr[pos] = tmp;
length++;
checkLen();
return true;
}
int BinarySearch(const char * name, int firstindex, int lastindex) {
if (lenght == 0) return 0; //number of items in array
if (firstindex == lastindex) return lastindex;
int tmp = lastindex - firstindex;
int pos = firstindex + tmp / 2; //position the new item should go to
if (tmp % 2)++pos;
if (lastindex == pos || firstindex == pos) return pos;
if (strcmp(name, Arr[pos]) < 0) return BinarySearch(name, firstindex, pos - 1);
if (strcmp(name, Arr[pos]) > 0) return BinarySearch(name, pos + 1, lastindex);
return pos;
}

A fixed version of BinarySearch
int BinarySearch(const char* name, int firstindex, int lastindex)
{
if (firstindex == lastindex) return lastindex;
int dist = lastindex - firstindex;
int mid = firstindex + dist / 2; //position the new item should go to
if (strcmp(name, Arr[mid]) < 0) return BinarySearch(name, firstindex, mid);
if (strcmp(name, Arr[mid]) > 0) return BinarySearch(name, mid + 1, lastindex);
return mid;
}
But you may directly use std::lower_bound:
// Assuming std::vector<std::string> Arr;
void CReg::AddCar(const std::string& name)
{
auto it = std::lower_bound(Arr.begin(), Arr.end(), name);
Arr.insert(it, name);
}

Related

Leetcode #33 TIme Limit Exceeded

https://leetcode.com/problems/search-in-rotated-sorted-array/
The question requires that the solution be O(log n) and I believe that my solution is O(log n) since my process of finding the smallest element is O(log n) and then using binary search to find the target value is also O(log n). However, my code is exceeding the time limit.
int search(vector<int>& nums, int target) {
if(nums.size() == 0){
return -1;
}
int left = 0;
int right = nums.size() - 1;
while(left < right){
int middle = left + (right - left) / 2;
if(nums[left] < nums[middle]){
left = middle;
}
else{
right = middle;
}
}
if(target >= nums[0]){
return binarySearch(nums, target, 0, left - 1);
}
else{
return binarySearch(nums, target, left, nums.size() - 1);
}
}
int binarySearch(vector<int>& nums, int target, int start, int end){
if(nums.size() == 0 || (start == end && nums[start] != target)){
return -1;
}
int mid = start + (end - start) / 2;
if(nums[mid] == target){
return mid;
}
if(nums[mid] > target){
return binarySearch(nums, target, start, mid - 1);
}
else{
return binarySearch(nums, target, mid, end);
}
}
I believe binarySearch can run into an endless loop. When end = start + 1 you will get mid = start so if nums[start] < target you end up making a recursive call with the same parameters as before.

Quick Sort with Insertion Sort

I've been working on this code for hours. The goal is to write an optimized QuickSort (with Insertion sort) on an array of pointers (which point to objects that can be compared). Insertion sort is supposed to be used with array sizes < 4.
So far, I have insertion sort working when I pass in an array < 4.
The quicksort is supposed to use the middle index as a pivot, and move everything < the pivot to the left of pivot, and everything > the pivot to the right of pivot.
I'm not even sure my overall approach to quickSort is correct. This is my first attempt at writing a quick sort. I could really use a nudge in the right direction here. The code that's commented out is something I've already tried.
If anything is unclear, let me know. Thanks for the help!
void quickSort(Comparable ** array, int fromIndex, int toIndex)
{
while (fromIndex < toIndex)
{
if ((toIndex - fromIndex +1 ) < 4)
{
insertionSort(array, fromIndex, toIndex);
break;
}
else
{
int pivotIndex = partition(array, fromIndex, toIndex);
quickSort(array, fromIndex, pivotIndex - 1);
quickSort(array, pivotIndex + 1, toIndex);
}
}
}
int partition(Comparable ** array, int fromIndex, int toIndex)
{
//Comparable *front = array[fromIndex+1];
int midIndex = (toIndex + fromIndex) / 2;
//int frontIndex = fromIndex;
//Comparable *back = array[toIndex - 1];
//int backIndex = toIndex - 1;
//Comparable *compare = front;
//int compareIndex = frontIndex;
SortFirstMiddleLast(array, fromIndex, midIndex, toIndex);
swap(array, midIndex, toIndex - 1);
int pivotIndex = toIndex - 1;
Comparable * pivot = array[pivotIndex];
int indexLeft = fromIndex + 1;
int indexRight = toIndex - 2;
bool sortFinished = false;
while (*array[indexLeft] < *pivot)
{
indexLeft++;
}
while (*array[indexRight] > *pivot)
{
indexRight--;
}
if ((*array[indexLeft] >= *pivot) && (*array[indexRight] <= *pivot))
{
if (indexLeft < indexRight)
{
swap(array, indexLeft, indexRight);
indexLeft++;
indexRight--;
sortFinished = true;
}
}
if (sortFinished == true)
{
swap(array, pivotIndex, indexLeft);
pivotIndex = indexLeft;
return pivotIndex;
}
// ++frontIndex; // advance to next element
// while (*array[frontIndex] < *array[backIndex])
// {
// // search forward for out of order element
// while ((*array[frontIndex] < *array[backIndex]) && (*array[fromIndex] > *array[frontIndex]))
// ++frontIndex;
// //search backward for out of order element
// while ((*array[frontIndex] < *array[backIndex]) && (*array[compareIndex] <= *array[backIndex]))
// --backIndex;
// swap(array, frontIndex, backIndex);
// }
// //insert mid position comparison element
// if (*array[compareIndex] >= *array[frontIndex])
// {
// swap(array, fromIndex, frontIndex);
// returnValue = frontIndex;
// }
// else
// {
// swap(array,fromIndex, (frontIndex - 1));
// returnValue = (frontIndex - 1);
// }
// return returnValue;
}
void swap(Comparable ** array, int swapIndex1, int swapIndex2)
{
Comparable * temp = array[swapIndex1];
array[swapIndex1] = array[swapIndex2];
array[swapIndex2] = temp;
}
void SortFirstMiddleLast(Comparable ** array, int fromIndex, int midIndex, int toIndex)
{
// first must be less than mid, must be less than last
if (*array[fromIndex] > *array[midIndex])
{
swap(array, fromIndex, midIndex);
}
if (*array[fromIndex] > *array[toIndex - 1])
{
swap(array, fromIndex, toIndex - 1);
}
if (*array[midIndex] > *array[toIndex - 1])
{
swap(array, midIndex, toIndex - 1);
}
}
void insertionSort(Comparable ** array, int fromIndex, int toIndex)
{
for (unsigned i = fromIndex + 1; i < toIndex; i++)
{
for (unsigned j = i; j > 0; j--)
{
if (*array[j] < *array[j - 1])
{
swap(array, j, j-1);
}
else
break;
}
}
}

Speeding up comparison of doubles in C++ [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I have a function that uses binary search to find the index in a sorted array of doubles such that a "search value" is greater than or equal to the value in the array at that index but strictly less than the value in the array at the subsequent index, if sorted ascending. The input array can be sorted ascending or descending.
I have profiled my code on Microsoft Visual Studio 2012 which shows that 12% of the time is spent in this function while 8% of the time is spent doing a comparison between the "search value" and a value in the array. I would like to explore the possibility of speeding up this function.
/**
Binary Search algorithm for a sorted array of doubles
_sortedArr could be sorted ascending or descending
Find the index in the array _sortedArr such that:
_sortedArr[lowerIndex] <= _valToFind < _sortedArr[lowerIndex+1]
*/
size_t findInArray(const double _sortedArr[], size_t _len, double _valToFind)
{
size_t startIndex = 0;
if( _len <= 1 ) return startIndex;
// Determine if the array is sorted ascending or descending
unsigned int isAscending = (_sortedArr[_len-1] > _sortedArr[startIndex]);
// To avoid looping through the array, detect edge cases first
if( isAscending ) {
if( _valToFind < _sortedArr[startIndex+1] ) return startIndex;
if( _valToFind >= _sortedArr[_len-1] ) return _len-1;
} else {
if( _valToFind > _sortedArr[startIndex+1] ) return startIndex;
if( _valToFind <= _sortedArr[_len-1] ) return _len-1;
}
size_t lowerIndex = startIndex + 1;
size_t upperIndex = _len - 1;
size_t midIndex = 0;
// Binary search loop
while (upperIndex - lowerIndex > 1)
{
midIndex = (upperIndex + lowerIndex) >> 1; // (upperIndex+lowerIndex)/2
// 8% of time spent executing the if-clause
if (_valToFind >= _sortedArr[midIndex] == isAscending)
lowerIndex = midIndex;
else
upperIndex = midIndex;
}
return lowerIndex;
}
The following is a way to test this function:
int main (int argc, char *argv[])
{
const double arr[] = {-3.0000000000000000, -2.5714285714285716, -2.1428571428571432,
-1.7142857142857146, -1.2857142857142860, -0.85714285714285743,
-0.42857142857142888, -3.3306690738754696e-016, 0.42857142857142821,
0.85714285714285676, 1.2857142857142854, 1.7142857142857140,
2.1428571428571423, 2.5714285714285707, 2.9999999999999991};
size_t index = findInArray(arr, 15, 0.0);
std::cout << "Index is: " << index << std::endl;
return 0;
}
When I change the if-clause (8% of the time spent here) to use the less-than comparison, there is no noticeable performance improvement:
if (!(_valToFind < _sortedArr[midIndex]) == isAscending)
The only difference in the disassembly with this change was the use of 'ja' rather than jb.
Any ideas would be appreciated.
Perhaps attempt to remove the conditional branch in the code.
size_t luIndex[2] = { startIndex + 1, _len - 1 };
size_t &lowerIndex = luIndex[0];
size_t &upperIndex = luIndex[1];
size_t midIndex = 0;
// Binary search loop
while (upperIndex - lowerIndex > 1)
{
midIndex = (upperIndex + lowerIndex) >> 1; // (upperIndex+lowerIndex)/2
luIndex[_valToFind >= _sortedArr[midIndex] != isAscending] = midIndex;
}
return lowerIndex;
You can take one of the comparisons out of the loop:
size_t findInArray(const double _sortedArr[], size_t _len, double _valToFind)
{
size_t startIndex = 0;
if( _len <= 1 ) return startIndex;
// Determine if the array is sorted ascending or descending
unsigned int isAscending = (_sortedArr[_len-1] > _sortedArr[startIndex]);
size_t lowerIndex = startIndex + 1;
size_t upperIndex = _len - 1;
size_t midIndex = 0;
// To avoid looping through the array, detect edge cases first
if( isAscending ) {
if( _valToFind < _sortedArr[startIndex+1] ) return startIndex;
if( _valToFind >= _sortedArr[_len-1] ) return _len-1;
// Binary search loop for isAscending == true
while (upperIndex - lowerIndex > 1)
{
midIndex = (upperIndex + lowerIndex) >> 1; // (upperIndex+lowerIndex)/2
if (_valToFind >= _sortedArr[midIndex])
lowerIndex = midIndex;
else
upperIndex = midIndex;
}
} else {
if( _valToFind > _sortedArr[startIndex+1] ) return startIndex;
if( _valToFind <= _sortedArr[_len-1] ) return _len-1;
// Binary search loop for isAscending == false
while (upperIndex - lowerIndex > 1)
{
midIndex = (upperIndex + lowerIndex) >> 1; // (upperIndex+lowerIndex)/2
if (_valToFind >= _sortedArr[midIndex])
upperIndex = midIndex;
else
lowerIndex = midIndex;
}
}
return lowerIndex;
}

Binary Search C++, STATUS_ACCESS_VIOLATION

the thing is that we are tring to do for first time a binary search function for a vector class, but I dont really know the reason why this is not working. Does anyone know what could be wrong(Status acces violation when the number is not in the vector array)??
// size_ is de number of used elements i the array
int Vector::bsearch(int value) const
{
int first = 0;
int last = size_ - 1;
int Substraction = size_ /2;
while(last >= first)
{
Substraction = first + (last - first) / 2;
if(array_[Substraction] > value)
last = Substraction;
else if(array_[Substraction] < value)
first = Substraction;
else if(array_[Substraction] == value)
return Substraction;
}
return CS170::Vector::NO_INDEX;
}
//SOLVED
int Vector::bsearch(int value) const
{
unsigned first = 0;
unsigned last = size_ - 1;
unsigned int mid;
if(value < array_[0] || value > array_[size_ - 1])
return CS170::Vector::NO_INDEX;
while(last >= first)
{
mid = first + (last - first) / 2;
if(value < array_[mid])
last = mid - 1;
else if(array_[mid] < value)
first = mid + 1;
else
return mid;
}
return CS170::Vector::NO_INDEX;
}
You're not excluding the element you just tested before the next loop. And your choice of variable names, Subtraction is dreadful. Its a midpoint.
int first = 0;
int last = size_-1;
int mid = 0;
while(last >= first)
{
mid = first + (last - first) / 2;
if(value < array_[mid])
last = mid-1; // don't include element just tested
else if(array_[mid] < value)
first = mid+1; // don't include element just tested
else return mid;
}
return CS170::Vector::NO_INDEX
Your initialization is wrong -
int first = size_ - 1;
int last = first = 0;
should be -
int last = size_ - 1;
int first = 0;
Also, in while you should use the following condition -
while (last>first)

Having trouble inserting into heap

Below is my C++ code for inserting into a heap. The value for k is inserted but it's inserted at the bottom. I expected it to heapify with that while loop.
void Insert(heap1* myHeap, int k)
{
(myHeap->size)++;
int i = myHeap->size;
while (i > 1 && myHeap->H[i/2].key < k)
{
myHeap->H[i].key = myHeap->H[i/2].key;
i = i/2;
}
myHeap->H[i].key = k;
}
I do have a heapify procedure that I tried to use for this before this attempt that I know works within my other heap procedures. I just can't get it to work within Insert so I went with the above route. Below is heapify just in case its useful:
void heapify(heap1* myHeap, int i)
{
int l = 2 * i;
int r = 2 * i + 1;
int largest;
if (l <= myHeap->size && myHeap->H[l].key > myHeap->H[i].key)
largest = l;
else
largest = i;
if (r <= myHeap->size && myHeap->H[r].key > myHeap->H[largest].key)
largest = r;
if (largest != i)
{
myHeap->H[i].key = myHeap->H[i].key + myHeap->H[largest].key;
myHeap->H[largest].key = myHeap->H[i].key - myHeap->H[largest].key;
myHeap->H[i].key = myHeap->H[i].key - myHeap->H[largest].key;
heapify(myHeap, largest);
}
}
If someone could lead me in the right direction on how to get it to restore its heap properties, I would largely appreciate it.
try using this code:
void insert(int heap[], int *n, int item){
(*n)++;
heap[*n] = item;
reheapify_upward(heap, *n);
}
void reheapify_upward(int heap[],int start){
int temp,parent;
if(start>1){
parent=start/2;
if(heap[parent]<heap[start]){
temp=heap[start];
heap[start]=heap[parent];
heap[parent]=temp;
reheapify_upward(heap,parent);
}
}
}