I have written this code after studying from Introduction to Algorithm. I am unable to find out what is the problem with the code. I have written the code for heapsort and it runs well. heap_extract_max() will return the maximum value. heap_increase_key() increase the priority of an element. Here I have written program for priority queue using singly linked list which runs well.
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
void max_heapify(std::vector<T>& array, size_t index)
{
size_t largest;
size_t left = (2*index) + 1;
size_t right = left + 1;
if(left < array.size() && array[left] > array[index])
largest = left;
else
largest = index;
if(right < array.size() && array[right] > array[largest])
largest = right;
if(largest != index)
{
int tmp = array[index];
array[index] = array[largest];
array[largest] = tmp;
max_heapify(array, largest);
}
}
template<typename T>
void build_max_heap(std::vector<T>& array)
{
for(size_t i = (array.size()/2) - 1; i >= 0; i--)
max_heapify(array, i);
}
template<typename T>
T heap_maximum(std::vector<T>& array)
{
return array[0];
}
template<typename T>
T heap_extract_max(std::vector<T>& array)
{
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
}
else
{
T max = array[0];
array[0] = array[array.size() - 1];
//array.size() = array.size() - 1;
max_heapify(array, 1);
return max;
}
}
template<typename T>
void heap_increase_key(std::vector<T>& array, size_t index, T value)
{
if(value < array[index])
{
std::cerr <<"New value is smaller than the current value\n";
return;
}
else
{
array[index] = value;
while(index > 0 && array[(index/2) - 1] < array[index])
{
std::swap(array[index], array[(index/2) - 1]);
index = (index/2) - 1;
}
}
}
template<typename T>
void max_heap_insert(std::vector<T>& array, T value)
{
array[array.size()] = -1;
heap_increase_key(array, array.size(), value);
}
int main()
{
std::vector<int> v({1, 2, 6, 3, 7});
build_max_heap(v);
std::cout << heap_extract_max(v)<<"\n";
for(size_t i = 0; i < v.size(); i++)
{
std::cout << v[i] << " ";
}
std::cout << "\n";
}
It is not showing any output. I am writing commands
$ g++ -std=c++11 priorityqueue.cpp -o priorityqueue
$ ./priorityqueue
Problem is with the below function what will be return for if case
because of that
Control may reach end of non-void function
template<typename T>
T heap_extract_max(std::vector<T>& array)
{
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
}
else
{
T max = array[0];
array[0] = array[array.size() - 1];
//array.size() = array.size() - 1;
max_heapify(array, 1);
return max;
}
}
Add return -1 or anything else for if case
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
return -1;
}
second problem
for(size_t i = (array.size()/2) - 1; i >= 0; i--)
Comparison of unsigned expression >= 0 is always true
Try changing to:(as suggested by Serge Rogatch)
for(int64_t i = (int64_t(array.size())/2) - 1; i >= 0; i--)
As well as there is problem with extracting it
Before change result was
7
2 3 6 1 2
Program ended with exit code: 0
Because of wrong handling of remove .Handled removed properly in below code
template<typename T>
T heap_extract_max(std::vector<T>& array)
{
if(array.size() < 0)
{
std::cerr << "Heap Underflow \n";
return -1;
}
else
{
T max = array[0];
array[0] = array[array.size() - 1];
array.erase(std::remove(array.begin(), array.end(), array[0]),
array.end());
array.shrink_to_fit();
max_heapify(array, 0);
return max;
}
}
After change
7
6 3 1 2
Program ended with exit code: 0
It seems your program enters an infinite loop or crashes. I see a problem here:
for(size_t i = (array.size()/2) - 1; i >= 0; i--)
Because i is unsigned, it is always i >= 0. Also, for array.size() <= 1, you initialize it with some large positive integer, because i tries to go negative, but size_t is never negative, so the number wraps.
Try changing to:
for(int64_t i = (int64_t(array.size())/2) - 1; i >= 0; i--)
Also you seem to confuse 0- and 1-based array indexing, and you should do array.pop_back() in place of //array.size() = array.size() - 1;. Furthermore, it seems you intended array[1] instead of array[0] here:
T max = array[0];
array[0] = array[array.size() - 1];
If you stick with 1-based indexing, you should place and keep a dummy element at index 0 in your array:
std::vector<int> v({/*dummy*/-1, 1, 2, 6, 3, 7});
Array size is never negative, so you don't need if(array.size() < 0) and what's in then clause.
Though 0-based indexing is more natural in C++ and heap can be implemented with it too. For this you would need to revise all the index arithmetic like:
size_t left = (2*index) + 1;
size_t right = left + 1;
and
array[(index/2) - 1]
Related
I'm trying to print the last level in a min heap. I thought I had code that works, but one of the test cases fail. In terms of the test cases, I only have access to how the output does not match.
Here is my code:
#include "MinHeap.h"
#include <math.h>
using std::log2;
vector<int> lastLevel(MinHeap & heap)
{
// Your code here
vector<int> leaves;
int capacity = pow(2, log2(heap.elements.size()) + 1) - 1;
for (unsigned leaf = capacity / 2; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
}
And here is the MinHeap class that goes along with it:
#include "MinHeap.h"
MinHeap::MinHeap(const vector<int> & vector)
{
int inf = numeric_limits<int>::min();
elements.push_back(inf);
elements.insert(elements.end(), vector.begin(), vector.end());
buildHeap();
}
MinHeap::MinHeap()
{
int inf = numeric_limits<int>::min();
elements.push_back(inf);
}
void MinHeap::buildHeap()
{
std::sort(elements.begin() + 1, elements.end());
}
void MinHeap::heapifyDown(int index)
{
int length = elements.size();
int leftChildIndex = 2 * index;
int rightChildIndex = 2 * index + 1;
if (leftChildIndex >= length)
return; // index is a leaf
int minIndex = index;
if (elements[index] > elements[leftChildIndex]) {
minIndex = leftChildIndex;
}
if ((rightChildIndex < length)
&& (elements[minIndex] > elements[rightChildIndex])) {
minIndex = rightChildIndex;
}
if (minIndex != index) {
// need to swap
int temp = elements[index];
elements[index] = elements[minIndex];
elements[minIndex] = temp;
heapifyDown(minIndex);
}
}
void MinHeap::heapifyUp(int index)
{
if (index < 2)
return;
int parentIndex = index / 2;
if (elements[parentIndex] > elements[index]) {
int temp = elements[parentIndex];
elements[parentIndex] = elements[index];
elements[index] = temp;
heapifyUp(parentIndex);
}
}
void MinHeap::insert(int newValue)
{
int length = elements.size();
elements.push_back(newValue);
heapifyUp(length);
}
int MinHeap::peek() const
{
return elements.at(1);
}
int MinHeap::pop()
{
int length = elements.size();
int p = -1;
if (length > 1) {
p = elements[1];
elements[1] = elements[length - 1];
elements.pop_back();
heapifyDown(1);
}
return p;
}
void MinHeap::print() const
{
if (elements.size() > 1) {
int length = elements.size();
cout << "[";
for (int i = 1; i < length - 1; i++) {
cout << elements[i] << ", ";
}
cout << elements[elements.size() - 1] << "]" << endl;
} else {
cout << "[ ]" << endl;
}
}
Here is the output I get showing one of the test cases fail:
tests.cpp:31: FAILED:
REQUIRE( s_lastLevel(h) == lastLevel(h) )
with expansion:
{ 1804289383 (0x6b8b4567), 1681692777 (0x643c9869) }
==
{ 1681692777 (0x643c9869) }
===============================================================================
test cases: 1 | 1 failed
assertions: 3 | 2 passed | 1 failed
I'm not sure why my initial approach is failing. Much help is appreciated.
It seems like the problem is in this line:
int capacity = pow(2, log2(heap.elements.size()) + 1) - 1;
What you are doing here is equivalent to:
int capacity = 2 * heap.elements.size() - 1;
What you instead want to do is get the index of the parent of the last element and increment by one as the starting position of your iteration. Since children of a node at i are at 2i and 2i+1, you can simply divide the index of the last node (n-1) by two and add one. You can check that this must be a leaf since its children would be at 2 * ((n-1)/2 + 1) and 2 * ((n-1)/2 + 1) + 1 which are both guaranteed equal or grater than n. So this will return all leaves:
int start = (heap.elements.size() - 1) / 2 + 1;
for (unsigned leaf = start; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
If it is just the last level you want, start at the largest power of two smaller than the index of the last element (n-1):
int start = 1 << (int)(log2(heap.elements.size()-1));
for (unsigned leaf = start; leaf < heap.elements.size(); leaf++) {
leaves.push_back(heap.elements[leaf]);
}
return leaves;
I have array(of numbers) with size N. I need to find minimum element which is unique,so if arr[5] ={1,2,3,1,2}, answer is 3.
I tried that with following code:
Int n = sizeof(arr)/sizeof(arr[0]);
sort(arr,arr + n);
for(int i = 0;i<N;i++){
for(int j = 0;j<N;j++){
if(arr[i] == arr[j]){
remove(arr,arr+n,i);
remove(arr,arr+n,j);
}
}
}
But problem is that this only work if I have 2 identical elements of arr.I could create if conditions for number of identical, but I can have 3 or 4 or 1000,so it will be pretty odd. So what is more elagant way to do this? Thank you in advance.
try this code, this uses an unordered map
int m = 2147483647;
int int_array[] = { 1,2,3,3,1,6,7,7,9 };
unordered_map<int, int> map;
for (int i = 0; i < sizeof(int_array) / sizeof(int_array[0]); i++) {
map[int_array[i]] = map[int_array[i]] + 1;
}
unordered_map<int, int>::iterator itr;
for (itr = map.begin(); itr != map.end(); itr++)
{
if (itr->second == 1) {
if (itr->first < m) {
m = itr->first;
}
}
}
printf("minimum unique is %d", m);
after sorting the array you can count the number of the dublicated members , if the member is unique then its count equals zero :
int main()
{
int arr[] = { 1, 2, 1, 3, 4, 1, 2 };
int n = sizeof(arr) / sizeof(int);
sort(arr, arr + n);
int count = 0;
int unique = -1;
for (int i = 0; unique == -1 && i < n - 1; ++i) {
if (arr[i] != arr[i + 1]) {
if (count==0)
unique = arr[i];
else
count = 0;
}
else {
count++;
}
}
if (count == 0 && unique ==-1)
unique = arr[n-1];
cout << unique;
return 0;
}
I propose the following code:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int arr[5] = { 1,2,3,2,1 };
int N = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + N);
int index = -1;
// Check first element is different comparing with second one.
// If the array is only one element, then first element is unique
if (N == 1 || arr[0] != arr[1]) {
index = 0;
}
else {
int i = 1;
while (i < N - 1 && index == -1) {
// Check number is different to previous and different to next value
if (arr[i - 1] != arr[i] && arr[i] != arr[i + 1]) {
index = i;
}
else
{
i++;
}
}
if (index == -1) {
// No found, check last element comparing with previous
if (arr[i - 1] != arr[i]) {
index = i;
}
}
}
if (index != -1) {
// Have found min value
cout << "Min not repeated value is " << arr[index] << endl;
}
else {
// All elements are repeated
cout << "No min value" << endl;
}
}
Once the array is sorted, I compare each value with previous and next value to check it is unique. But for first and last element are a special case.
Using what I said in the comments, with an extra bool.
int arr[] = { 1, 2, 1, 3, 4, 1, 2 };
int n = sizeof( arr ) / sizeof( int );
std::sort( arr, arr + n );
bool match = false;
for ( int i = 0; i < n; ++i ) {
if ( i == n - 1 || arr[i] != arr[i + 1] ) {
if ( match )
match = false;
else
return arr[i];
} else {
match = true;
}
}
return -1; // made up number in case all duplicates
If the two values are equal, then we know that we can't use that value again, so I set match to true. If they are not equal, then if it was already disqualified, I ignore it and set match back to false, otherwise, return that value.
There are more elegant ways to do this; this is just the simplest.
int n;//input size of array
cin >> n;
vector <int> a(n);
vector <int> in;
for (int i = 0; i < n; i++)
cin >> a[i];//input array elements
if (n == 1) {
cout << "1" << "\n";
return 0;
}
for (int i = 1; i <= n ; i++)//to get longest incresing subsequence in the array
{
int flag = 0, j = i;
while (j < n && a[j] >= a[j - 1] ) {
j++;
flag = 1;
}
if (flag == 1) {
in.push_back(j - i + 1);
i = j;
}
}
int maxval = in[0]; //to get maximum sized element from in
for (int i = 1; i < in.size(); i++)
if (in[i] > maxval)
maxval = in[i];
cout << maxval << "\n";
I tried the same code for values < 10000 it's working fine...i've replaced all int's by long long int's then also it's showing vector subscript out of range error...
Sample input :
10
49532 49472 49426 49362 49324 49247 49165 49162 49108 49093
i'm expecting 0 but it shows "vector subscript out of range"
The reason of the problem is this statement
int maxval = in[0];//to get maximum sized element from in
The vector in is empty when this input is used
10
49532 49472 49426 49362 49324 49247 49165 49162 49108 49093
So you may not use the subscript operator.
You could write for example
int maxval = in.empty() ? 0 : in[0];
Fix this:
int maxval = in.size()? in[0]:0;
the vector class operator checks the index is between lower and upper limit of array which will be (0 -> size-1)
MSVC lib:
_NODISCARD _Ty& operator[](const size_type _Pos) noexcept { // strengthened
auto& _My_data = _Mypair._Myval2;
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(
_Pos < static_cast<size_type>(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _My_data._Myfirst[_Pos];
}
the problem is that the in.push_back never get called then the size is zero.
so in[0] call operator will throw exception index out range.
Homework: I'm just stumped as hell. I have algorithms set up, but I have no idea how to code this
Just to be clear you do not need arrays or to pass variables by reference.
The purpose of the project is to take a problem apart and using Top-Down_Design or scratch pad method develop the algorithm.
Problem:
Examine the numbers from 2 to 10000. Output the number if it is a Dual_Prime.
I will call a DualPrime a number that is the product of two primes. Ad where the two primes are not equal . So 9 is not a dual prime. 15 is ( 3 * 5 ) .
The output has 10 numbers on each line.
My Algorithm set-up
Step 1: find prime numbers.:
bool Prime_Number(int number)
{
for (int i = 2; i <= sqrt(number); i++)
{
if (number % 1 == 0)
return false;
}
return true;
}
Step 2: store prime numbers in a array
Step 3: Multiply each array to each other
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int j = 0; j < Size- 1; j++)
{
Dual_Prime[] = Arr[j] * Arr[j + 1]
}
}
Step 4: Bubble sort
void Bubble_Sort(int Array[], int Size) // Sends largest number to the right
{
for (int i = Size - 1; i > 0; i--)
for (int j = 0; j < i; j++)
if (Array[j] > Array[j + 1])
{
int Temp = Array[j + 1];
Array[j + 1] = Array[j];
Array[j] = Temp;
}
}
Step 5: Display New Array by rows of 10
void Print_Array(int Array[], int Size)
{
for (int i = 0; i < Size; i++)
{
cout << Dual_Prime[i] << (((j % 10) == 9) ? '\n' : '\t');
}
cout << endl;
}
I haven't learned dynamic arrays yet,
Although dynamic arrays and the sieve of Eratosthenes are more preferable, I tried to write minimally fixed version of your code.
First, we define following global variables which are used in your original implementation of Multiply_Prime_Numbers.
(Please check this post.)
constexpr int DP_Size_Max = 10000;
int DP_Size = 0;
int Dual_Prime[DP_Size_Max];
Next we fix Prime_Number as follows.
The condition number%1==0 in the original code is not appropriate:
bool Prime_Number(int number)
{
if(number<=1){
return false;
}
for (int i = 2; i*i <= number; i++)
{
if (number % i == 0)
return false;
}
return true;
}
In addition, Multiply_Prime_Numbers should be implemented by double for-loops as follows:
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int i = 0; i < Size; ++i)
{
for (int j = i+1; j < Size; ++j)
{
Dual_Prime[DP_Size] = Array[i]*Array[j];
if(Dual_Prime[DP_Size] >= DP_Size_Max){
return;
}
++DP_Size;
}
}
}
Then these functions work as follows.
Here's a DEMO of this minimally fixed version.
int main()
{
int prime_numbers[DP_Size_Max];
int size = 0;
for(int j=2; j<DP_Size_Max; ++j)
{
if(Prime_Number(j)){
prime_numbers[size]=j;
++size;
}
}
Multiply_Prime_Numbers(prime_numbers, size);
Bubble_Sort(Dual_Prime, DP_Size);
for(int i=0; i<DP_Size;++i){
std::cout << Dual_Prime[i] << (((i % 10) == 9) ? '\n' : '\t');;
}
std::cout << std::endl;
return 0;
}
The Sieve of Eratosthenes is a known algorithm which speeds up the search of all the primes up to a certain number.
The OP can use it to implement the first steps of their implementation, but they can also adapt it to avoid the sorting step.
Given the list of all primes (up to half the maximum number to examine):
Create an array of bool as big as the range of numbers to be examined.
Multiply each distinct couple of primes, using two nested loops.
If the product is less than 10000 (the maximum) set the corrisponding element of the array to true. Otherwise break out the inner loop.
Once finished, traverse the array and if the value is true, print the corresponding index.
Here there's a proof of concept (implemented without the OP's assignment restrictions).
// Ex10_TwoPrimes.cpp : This file contains the 'main' function. Program execution begins and ends there.
#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void Homework_Header(string Title);
void Do_Exercise();
void Sieve_Of_Eratosthenes(int n);
void Generate_Semi_Prime();
bool Semi_Prime(int candidate);
bool prime[5000 + 1];
int main()
{
Do_Exercise();
cin.get();
return 0;
}
void Do_Exercise()
{
int n = 5000;
Sieve_Of_Eratosthenes(n);
cout << endl;
Generate_Semi_Prime();
}
void Sieve_Of_Eratosthenes(int n)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
memset(prime, true, sizeof(prime));
for (int p = 2; p*p <= n; p++)
{
// If prime[p] is not changed, then it is a prime
if (prime[p] == true)
{
// Update all multiples of p
for (int i = p * p; i <= n; i += p)
prime[i] = false;
}
}
}
bool Semi_Prime(int candidate)
{
for (int index = 2; index <= candidate / 2; index++)
{
if (prime[index])
{
if (candidate % index == 0)
{
int q = candidate / index;
if (prime[q] && q != index)
return true;
}
}
}
return false;
}
void Generate_Semi_Prime()
{
for (int i = 2; i <= 10000; i++)
if (Semi_Prime(i)) cout << i << "\t";
}
My program is suppose to count how many times the data in my array changed from increase to decrease or vice versa. For example: {1,2,3,4,3,4}
changes twice as the first four elements are increasing then decrease o 3 (causing one change) and then increase back to four causing a second change.
The idea in my code was that every time greater or decrease changed to false it would count when it happened but I cannot get it to work.
Any help is greatly appreciated as I am really struggling with this!
unsigned count = 0;
bool greater = true;
bool decrease = true;
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else
greater = false;
count++;
}
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] < a[i]){
decrease = true;
}
else
decrease = false;
count++;
}
return count;
Your logic is wrong
you may do something like
enum class EDirection { none, decreasing, increasing};
std::size_t count_direction_changes(const std::vector<int>& v)
{
std::size_t res = 0;
EDirection direction = EDirection::none;
for (std::size_t i = 1; i != v.size(); ++i) {
const int diff = v[i] - v[i - 1];
switch (direction)
{
case EDirection::none: {
if (diff == 0) {
break;
}
direction = (diff > 0) ? EDirection::increasing : EDirection::decreasing;
break;
}
case EDirection::increasing: {
if (diff < 0) {
++res;
direction = EDirection::decreasing;
}
break;
}
case EDirection::decreasing: {
if (diff > 0) {
++res;
direction = EDirection::increasing;
}
break;
}
}
}
return res;
}
Demo
You must change your loops. First of all you should stop the loop at size-1. Because you are comparing with next element and you can go out of bounds if your for is running until elements instead of elements-1.
Furthermore, you have a logic issue. If you are using a boolean variable as flag, you should check if it's true or not before increasing your counter. And in case you increments your counter you must reset that flag. Something similar to down loop should work. Maybe there is some little mistake because I don't have anythin to test it now. But it should be something similar to this.
for (unsigned i = 0; i < elements-1; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else{
greater = false;
}
if(greater){
count++;
greater = false;
}
}
This is a lot like Jarod42's, but seeing as I've already coded it will throw it out there. BTW, I use the slightly awkward v[n] < v[n - 1] so it's only necessary to implement operator< to apply the algo to a user-defined type (i.e. not operator> as well).
#include <iostream>
#include <vector>
template <typename T>
size_t changes(const std::vector<T>& v)
{
if (v.size() <= 2) return 0;
size_t count = 0;
enum { Increasing, Decreasing, Flat } last;
last = v[0] < v[1] ? Increasing : v[1] < v[0] ? Decreasing : Flat;
for (size_t i = 2; i < v.size(); ++i)
if (v[i - 1] < v[i])
{
if (last == Decreasing) ++count;
last = Increasing;
}
else if (v[i] < v[i - 1])
{
if (last == Increasing) ++count;
last = Decreasing;
}
return count;
}
int main()
{
std::cout << changes<int>({ 1, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 3, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 4, 3, 5, 4, 2, 2, 1 }) << '\n';
}
See it run here.
Here is another approach, similar to Tony's and Jarod's:
#include <vector>
#include <cassert>
#include <iostream>
size_t countTrendChanges(const std::vector<int>& a) {
if (a.size() < 3)
return 0;
int trend = 0;
size_t count = 0;
for (size_t i = 1; i != a.size(); ++i) {
int new_trend = (a[i-1] < a[i]) - (a[i] < a[i-1]);
if (new_trend == 0)
continue;
if (trend != 0 && new_trend != trend)
count++;
trend = new_trend;
}
return count;
}
int main() {
assert(countTrendChanges({}) == 0);
assert(countTrendChanges({1}) == 0);
assert(countTrendChanges({3,2,1}) == 0);
assert(countTrendChanges({1,2,3}) == 0);
assert(countTrendChanges({1,2,2,3}) == 0);
assert(countTrendChanges({3,2,1,2,3}) == 1);
assert(countTrendChanges({1,2,3,2}) == 1);
assert(countTrendChanges({2,1,1,2}) == 1);
assert(countTrendChanges({1,2,2,1}) == 1);
assert(countTrendChanges({1,2,3,4,3,4}) == 2);
}