I compile like this:
clang++ -std=c++11 test.cpp MinHeap.cpp -o test
Implementation is failing test2 "Assertion failed: (array[i] == i), function test2, file test.cpp, line ...
Abort trap: 6". The test2 is creating an array of size 10000 (with ints from 0 to 10000 in random order) and using heapsort and MinHeap class to sort it in order.
100% heapsort is correctly implemented. I've gone through the logic of the main MinHeap functions (insert -> bubble_up , extract -> bubble_down) but can't find the bugs.
test.cpp
#include <cassert>
#include <cstdlib>
#include "MinHeap.hpp"
#include <iostream>
void heapsort(int* const array, int size){
MinHeap heap;
for (int i = 0; i < size; i++){
heap.insert(array[i]);
}
for (int i = 0; i < size; i++){
array[i] = heap.extractMin();
}
}
void test2(){
int size = 10000;
int* array = new int[size];
for(int i = 0; i < size; i++){
array[i] = i;
}
unsigned int seed = 2019;
std::srand(seed);
for(int i = 0; i < size; i++){
int index1 = std::rand() % size;
int index2 = std::rand() % size;
int number1 = array[index1];
array[index1] = array[index2];
array[index2] = number1;
}
heapsort(array, size);
for(int i = 0; i < size; i++){
assert(array[i] == i);
}
delete [] array;
}
int main(){
insert_test();
extract_test();
test2();
return 0;
}
MinHeap.hpp
#ifndef MINHEAP_HPP
#define MINHEAP_HPP
class MinHeap{
public:
MinHeap();
// MinHeap(const MinHeap& other);
// MinHeap& operator=(const MinHeap& other);
~MinHeap();
void insert(int number);
int extractMin();
bool isEmpty() const;
void toString() const;
private:
void swap(int &a, int &b);
void expand();
void bubble_up(int start);
void bubble_down(int start);
void fit();
int find_min(int a, int b, int c);
int* array;
int size;
int capacity;
};
#endif
MinHeap.cpp
#include "MinHeap.hpp"
#include <string>
#include <iostream>
MinHeap::MinHeap(){
size = 0;
capacity = 10000;
array = new int[capacity];
}
MinHeap::~MinHeap(){
delete[] array;
}
void MinHeap::insert(int number){
if(isEmpty()){
array[0] = number;
size++;
return;
}
if (size == capacity){
throw std::runtime_error("Overflow, int not inserted")
}
array[size] = number;
bubble_up(size);
size++;
return;
}
void MinHeap::swap(int &a, int &b){
int hold = a;
a = b;
b = hold;
}
int MinHeap::extractMin(){
if(isEmpty()){
throw std::runtime_error("Not Valid");
}
else if (size == 1){
size--;
return array[0];
}
int min = array[0];
array[0] = array[size-1];
size--;
bubble_down(0);
return min;
}
void MinHeap::bubble_up(int start){
int child = start;
int parent = (child - 1)/2;
if (start == 1){
if (array[0] > array[1]){
swap(array[0], array[1]);
}
}
while (parent >= 0 and array[child] < array[parent]){
swap(array[child], array[parent]);
child = parent;
parent = (child - 1)/2;
}
}
void MinHeap::bubble_down(int start){
int parent = start;
int left = (2*parent)+1;
int right = (2*parent)+2;
if (left > size){
if(array[parent] < array[right]){
swap(array[parent], array[right]);
}
return;
}
if (right > size){
if(array[parent] < array[left]){
swap(array[parent], array[left]);
}
return;
}
int min = find_min(array[parent], array[left], array[right]);
if (min == array[left]){
swap(array[left], array[parent]);
bubble_down(left);
}
else if (min == array[right]){
swap(array[right], array[parent]);
bubble_down(right);
}
return;
}
int MinHeap::find_min(int a, int b, int c){
if (a < b and a < c){
return a;
}
else if (b < a and b < c){
return b;
}
return c;
}
bool MinHeap::isEmpty() const{
if (size > 0){
return false;
}
return true;
}
It looks like the last run through when the parent is 9466 in the bubble_down function, the array is going out of bounds because the limit is 10,000 and you are trying to compare the right value as being (2 * parent) + 2 which gives you 18,934. I am not exactly sure what you are trying to accomplish, but I think that is where the bug lies.
if (left > size) {
if (array[parent] < array[right]) { // Breaking here!
swap(array[parent], array[right]);
}
return;
}
Related
I've been trying to make a dynamic array. My main method calls push_back() to add ints to an array 50 times. The push_back() method calls the grow_if_needed() method if the size of the array needs to be doubled. The size() method returns the current capacity of the array. And the toString method is for printing the array as a string. I keep getting this error at the end of the grow_if_needed() method.
#include <string>
class ArrayList
{
private:
static int capacity;
static int count;
public:
int& operator [](int i);
int *arrayPtr = new int[1];
ArrayList();
int * push_back(int m);
int * grow_if_needed();
int * erase(int m);
int size();
std::string toString();
};
#include "ArrayList.h"
using namespace std;
int ArrayList::capacity = 1;
int ArrayList::count = 0;
int & ArrayList::operator[](int i)
{
return arrayPtr[i];
}
ArrayList::ArrayList()
{
arrayPtr[0] = 0;
}
int * ArrayList::push_back(int m)
{
if (count == size()) {
grow_if_needed();
}
for (int i = size() - 1; i >= 0; i--) {
arrayPtr[i + 1] = arrayPtr[i];
}
arrayPtr[0] = m;
count++;
return arrayPtr;
}
int * ArrayList::grow_if_needed() {
int k;
capacity = size() * 2;
int * tempArray = new int[capacity];
for (k = 0; k < count; k++) {
tempArray[k] = arrayPtr[k];
}
while (k != capacity) {
tempArray[k] = 0;
k++;
}
delete [] arrayPtr;
arrayPtr = tempArray;
return arrayPtr;
}
int ArrayList::size()
{
return capacity;
}
string ArrayList::toString()
{
string num = "";
for (int i = 0; i <= size() - 1; i++) {
num += std::to_string(arrayPtr[i]) + " ";
}
return num;
}
In your push_back function you have this loop:
for (int i = size() - 1; i >= 0; i--) {
arrayPtr[i + 1] = arrayPtr[i];
}
Here size() - 1 is the top index, so in the first iteration when you do i + 1 you are out of bounds.
Also, this function is called push_back, but it attempts to add to the front? If it added to the end (the "back") you would not need the loop, and your problem would "magically" disappear.
I had this task in C++ where I had to implement a Stack only using arrays (and not using things like Vectors). The teacher gave us an interface to follow and some code to test our ArrayStack on. My problem is that when I create a stack, fill it with 100 elements then empty it the size is 4 (i set 4 for a minimum) and when the teacher code do the same (in the testStack function) the same check fails.
Heres my code:
#include <iostream>
#include <string>
#include <assert.h>
using namespace std;
template<typename T>
class Stack {
public:
// Adds new element to the top of the stack
virtual void push(T x) = 0;
// Returns the top element AND removes it from the stack
// If the stack is empty use 'throw std::out_of_range("<human_friendly_message>");'
virtual T pop() = 0;
// Returns the top element but does NOT remove it from the stack
// If the stack is empty use 'throw std::out_of_range("<human_friendly_message>");'
virtual T top() = 0;
// Returns the current number of elements in the stack
virtual int getSize() = 0;
// Returns the current capacity of the underlying data storage (array)
virtual int getCapacity() = 0;
// Returns true if the stack has no elements and false otherwise
virtual bool isEmpty() = 0;
};
template<typename T>
class ArrayStack : public Stack<T>{
private:
T* data;
int arraysize;
int N;
void resize(int capacity)
{
T* copy = new T[capacity];
for (int i = 0; i < N; i++)
copy[i] = data[i];
T* p = data;
data = copy;
delete [] p;
}
public:
ArrayStack(){
N = 0;
data = new T[4];
arraysize = 4;
}
ArrayStack(int n){
if (n < 1) n = 1;
N = 0;
data = new T[n];
arraysize = n;
}
bool isEmpty(){ return N == 0; }
void push(T x)
{
if (N == arraysize)
{
resize(2 * arraysize);
arraysize *= 2;
}
data[N] = x;
N++;
}
T pop()
{
if (isEmpty()){
throw out_of_range("Can't pop on empty stack");
}
else{
N--;
T k;
k = data[N];
if (N > 0 && N == arraysize / 4 && arraysize/2>=4)
{
resize(arraysize / 2);
arraysize /= 2;
}
return k;
}
}
T top()
{
if (isEmpty()) throw out_of_range("Can't top on empty stack");
return data[N - 1];
}
int getCapacity()
{
return arraysize;
}
int getSize()
{
return N;
}
~ArrayStack()
{
delete [] data;
}
};
template<class T>
void testStack(Stack<T> *& stack, int cap = 128) {
for (int i = 0; i < 100; i++) {
stack->push(i);
assert(stack->top() == i);
}
assert(stack->getCapacity() == cap);
assert(stack->getSize() == 100);
for (int i = 99; i >= 0; i--) {
assert(stack->top() == i);
stack->pop();
}
assert(stack->getCapacity() == 4);
assert(stack->isEmpty());
}
int main() {
try {
Stack<int> * stackI = new ArrayStack<int>();
testStack(stackI);
delete stackI;
Stack<float> * stackF = new ArrayStack<float>(1);
testStack(stackF);
delete stackF;
Stack<double> * stackD = new ArrayStack<double>(65536);
testStack(stackD, 65536);
delete stackD;
Stack<string> * stackS = new ArrayStack<string>();
stackS->push("string1");
stackS->push("string2");
stackS->push("string3");
stackS->push("string4");
for (int i = 0; i < 4; i++) {
stackS->pop();
}
assert(stackS->isEmpty());
cout << "All tests passed!" << endl;
}
catch (std::exception & ex) {
cout << ex.what() << endl;
}
return 0;
}
As you may have noticed, the problem occurs with the last stack, the one with an initial capacity of 65536.
If you print the capacity just before the failed assertion, you will notice that it's 65536.
It looks like the stack hasn't been resized at all.
Looking at your conditions for when to shrink the storage, there is a required condition that N == arraysize / 4.
Since N doesn't become greater than 100, and 65536 / 4 is 16384, this condition will never be true.
Replacing == with <= takes care of it:
N <= arraysize / 4
I have the code to build a max heap, but it keeps on returning the same array I give it. I'm sure its a minor error, but I cant seem to figure it out. Any help is appreciated.
Compilable sample code:
#include <iostream>
#include <cmath>
class Heaparr {
public:
Heaparr();
void insert(int da);
int getLeft(int i) { return 2 * i; }
int getRight(int i) { return (2 * i) + 1; }
int getParent(int i) { return i / 2; }
int getMax() { return maxHeap[0]; }
void print();
void reheap(int num);
void makeArray();
void Build_Max_Heap(int maxHeap[], int heap_size);
void Max_Heapify(int heapArray[], int i, int heap_size);
void heapSort(int heapArray[]);
private:
int size;
int* maxHeap;
int index;
int i;
};
Heaparr::Heaparr() {
maxHeap = nullptr;
size = 0;
}
void Heaparr::insert(int da) {
size++;
int* tmp = new int[size];
for (int i = 0; i < size - 1; i++) {
tmp[i] = maxHeap[i];
}
tmp[size - 1] = da;
delete[] maxHeap;
maxHeap = tmp;
}
void Heaparr::heapSort(int maxHeap[]) {
int heap_size = size;
int n = size;
int temp;
Build_Max_Heap(maxHeap, heap_size);
for (int i = n - 1; i >= 1; i--) {
temp = maxHeap[0];
maxHeap[0] = maxHeap[i];
maxHeap[i] = temp;
heap_size = heap_size - 1;
Max_Heapify(maxHeap, 0, heap_size);
}
for (int i = 0; i < 8; i++) {
std::cout << maxHeap[i] << std::endl;
}
}
void Heaparr::Build_Max_Heap(int maxHeap[], int heap_size) {
int n = size;
for (int i = floor((n - 1) / 2); i >= 0; i--) {
Max_Heapify(maxHeap, i, heap_size);
}
return;
}
void Heaparr::Max_Heapify(int heapArray[], int i, int heap_size) {
// int n = size;
int largest = 0;
int l = getLeft(i);
int r = getRight(i);
if ((l <= heap_size) && (heapArray[l] > heapArray[i])) {
largest = l;
} else {
largest = i;
}
if ((r <= heap_size) && (heapArray[r] > heapArray[largest])) {
largest = r;
}
int temp;
if (largest != i) {
temp = heapArray[i];
heapArray[i] = heapArray[largest];
heapArray[largest] = temp;
Max_Heapify(heapArray, largest, heap_size);
}
return;
}
int main(int argc, char* argv[]) {
int hArray[8] = {5, 99, 32, 4, 1, 12, 15, 8};
Heaparr t;
t.heapSort(hArray);
for (auto v : hArray) {
std::cout << v << ", ";
}
std::cout << std::endl;
}
I made some fixed to the code (i try not to changed much the original code):
The getLeft, getRight and getParent formulas were wrong (ex: when i == 0 children must be 1 and 2 and with your code are 0 and 1. The return type was also wrong, should be int (array index).
Do you receive in all methods a int[] except in insert and the member variable that are double[], changed all to int[], if you need changed back all to double
Using std::swap for swap values in the array.
Adding the length of the array to heapSort (inside the method this info is lost, need to be passed by parameter).
Notes:
I dont see where you use the member variable maxHeap, because all methods except getMax and insert use the array passed by parameter and not the member variable (perhaps you should initialized in the constructor or in heapSort method.
Try to use std::vector instead of C Array
Code:
#include <iostream>
#include <cmath>
class Heaparr {
public:
Heaparr();
void insert(int da);
int getLeft(int i) { return 2 * i + 1; }
int getRight(int i) { return 2 * i + 2; }
int getParent(int i) { return (i - 1) / 2; }
int getMax() { return maxHeap[0]; }
void print();
void reheap(int num);
void makeArray();
void Build_Max_Heap(int heapArray[], int heap_size);
void Max_Heapify(int heapArray[], int i, int heap_size);
void heapSort(int heapArray[], int heap_size);
private:
int size;
int* maxHeap;
int index;
int i;
};
Heaparr::Heaparr() {
maxHeap = nullptr;
size = 0;
}
void Heaparr::insert(int da) {
size++;
int* tmp = new int[size];
for (int i = 0; i < size - 1; i++) {
tmp[i] = maxHeap[i];
}
tmp[size - 1] = da;
delete[] maxHeap;
maxHeap = tmp;
}
void Heaparr::heapSort(int heapArray[], int heap_size) {
size = heap_size;
int n = size;
Build_Max_Heap(heapArray, heap_size);
for (int i = n - 1; i >= 1; i--) {
std::swap(heapArray[0], heapArray[i]);
heap_size = heap_size - 1;
Max_Heapify(heapArray, 0, heap_size);
}
}
void Heaparr::Build_Max_Heap(int heapArray[], int heap_size) {
int n = size;
for (int i = floor((n - 1) / 2); i >= 0; i--) {
Max_Heapify(heapArray, i, heap_size);
}
return;
}
void Heaparr::Max_Heapify(int heapArray[], int i, int heap_size) {
// int n = size;
int largest = 0;
int l = getLeft(i);
int r = getRight(i);
if ((l < heap_size) && (heapArray[l] < heapArray[i])) {
largest = l;
} else {
largest = i;
}
if ((r < heap_size) && (heapArray[r] < heapArray[largest])) {
largest = r;
}
if (largest != i) {
std::swap(heapArray[i], heapArray[largest]);
Max_Heapify(heapArray, largest, heap_size);
}
return;
}
int main(int argc, char* argv[]) {
int hArray[8] = {5, 99, 32, 4, 1, 12, 15, 8};
Heaparr t;
t.heapSort(hArray, sizeof(hArray)/sizeof(hArray[0]));
for (auto v : hArray) {
std::cout << v << ", ";
}
std::cout << std::endl;
return 0;
}
Output:
99, 32, 15, 12, 8, 5, 4, 1,
Tested in GCC 4.9.0 with C++11
If you're willing to consider alternative implementations, then here is one:
#define MIN_TYPE 0
#define MAX_TYPE ~0
template<int TYPE,typename ITEM>
class Heap
{
public:
Heap(int iMaxNumOfItems);
virtual ~Heap();
public:
bool AddItem(ITEM* pItem);
bool GetBest(ITEM** pItem);
protected:
int BestOfTwo(int i,int j);
void SwapItems(int i,int j);
protected:
ITEM** m_aItems;
int m_iMaxNumOfItems;
int m_iCurrNumOfItems;
};
template<int TYPE,typename ITEM>
Heap<TYPE,ITEM>::Heap(int iMaxNumOfItems)
{
m_iCurrNumOfItems = 0;
m_iMaxNumOfItems = iMaxNumOfItems;
m_aItems = new ITEM*[m_iMaxNumOfItems];
if (!m_aItems)
throw "Insufficient Memory";
}
template<int TYPE,typename ITEM>
Heap<TYPE,ITEM>::~Heap()
{
delete[] m_aItems;
}
template<int TYPE,typename ITEM>
bool Heap<TYPE,ITEM>::AddItem(ITEM* pItem)
{
if (m_iCurrNumOfItems == m_iMaxNumOfItems)
return false;
m_aItems[m_iCurrNumOfItems] = pItem;
for (int i=m_iCurrNumOfItems,j=(i+1)/2-1; j>=0; i=j,j=(i+1)/2-1)
{
if (BestOfTwo(i,j) == i)
SwapItems(i,j);
else
break;
}
m_iCurrNumOfItems++;
return true;
}
template<int TYPE,typename ITEM>
bool Heap<TYPE,ITEM>::GetBest(ITEM** pItem)
{
if (m_iCurrNumOfItems == 0)
return false;
m_iCurrNumOfItems--;
*pItem = m_aItems[0];
m_aItems[0] = m_aItems[m_iCurrNumOfItems];
for (int i=0,j=(i+1)*2-1; j<m_iCurrNumOfItems; i=j,j=(i+1)*2-1)
{
if (j+1 < m_iCurrNumOfItems)
j = BestOfTwo(j,j+1);
if (BestOfTwo(i,j) == j)
SwapItems(i,j);
else
break;
}
return true;
}
template<int TYPE,typename ITEM>
int Heap<TYPE,ITEM>::BestOfTwo(int i,int j)
{
switch (TYPE)
{
case MIN_TYPE: return *m_aItems[i]<*m_aItems[j]? i:j;
case MAX_TYPE: return *m_aItems[i]>*m_aItems[j]? i:j;
}
throw "Illegal Type";
}
template<int TYPE,typename ITEM>
void Heap<TYPE,ITEM>::SwapItems(int i,int j)
{
ITEM* pItem = m_aItems[i];
m_aItems[i] = m_aItems[j];
m_aItems[j] = pItem;
}
And here is a usage example:
typedef int ITEM;
#define SIZE 1000
#define RANGE 100
void test()
{
ITEM* pItem;
ITEM aArray[SIZE];
Heap<MIN_TYPE,ITEM> cHeap(SIZE);
srand((unsigned int)time(NULL));
for (int i=0; i<SIZE; i++)
{
aArray[i] = rand()%RANGE;
cHeap.AddItem(aArray+i);
}
for (int i=0; i<SIZE; i++)
{
cHeap.GetBest(&pItem);
printf("%d\n",*pItem);
}
}
Description:
This class stores up to N items of type T
It allows adding an item or extracting the best item
Supported operations are accomplished at O(log(n)), where n is the current number of items
Remarks:
T is determined at declaration and N is determined at initialization
The meaning of "best", either minimal or maximal, is determined at declaration
In order to support Heap<MIN,T> and Heap<MAX,T>, one of the following options must be viable:
bool operator<(T,T) and bool operator>(T,T)
bool T::operator<(T) and bool T::operator>(T)
T::operator P(), where P is a type, for which, one of the above options is viable
I have written a binary search like following. When I try to find 10, it's not showing me the result. What am I missing??
// BinarySearch.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void BinarySearch(int arr[],int value);
int * insertionshot(int arr[]);
int _tmain(int argc, _TCHAR* argv[])
{
int arr[10] = {1,2,3,10,5,9,6,8,7,4};
int value;
cin >> value ;
static int *ptr;// = new int[10];
ptr = insertionshot(arr);
BinarySearch(ptr,value);
return 0;
}
int * insertionshot(int arr[])
{
int ar[10];
for(int i =0;i < 10; i++)
{
ar[i] = arr[i];
}
int arrlength = sizeof(ar)/sizeof(ar[0]);
for(int a = 1; a <= arrlength -1 ;a++)
{
int b = a;
while(b > 0 && ar[b] < ar[b-1])
{
int temp;
temp = ar[b-1];
ar[b-1] = ar[b];
ar[b] = temp;
b--;
}
}
return ar;
}
void BinarySearch( int a[],int value)
{
int min,max,middle;
min = 0;
int ar[10];
for(int i =0;i < 10; i++)
{
ar[i] = a[i];
}
//printf("size of array = %d",sizeof(arr));
max = (sizeof(ar)/sizeof(ar[0]) -1);
middle = (min+max)/2;
while(min <= max)
{
if(ar[middle] == value)
{
cout << "The value found" << ar[middle];
break;
}
else if(ar[middle] < value)
{
min = middle +1;
}
else if(ar[middle] > value)
{
max = middle-1;
}
middle = (min+max)/2;
}
}
Finally i made it work,I think this code does not have any problem.This could help any one
// BinarySearch.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void BinarySearch(int arr[],int value);
int * insertionshot(int arr[],int);
int _tmain(int argc, _TCHAR* argv[])
{
int arr[10] = {1,2,3,10,5,9,6,8,7,4};
int * arr1 = new int[10];
for(int i = 0;i< sizeof(arr)/sizeof(arr[0]);i++)
{
arr1[i] = arr[i];
}
int value;
cin >> value ;
int *ptr = new int[10];
ptr = insertionshot(arr1,10); // address of sorted array will be returned.
BinarySearch(ptr,value);
arr1 = 0;
ptr =0;
delete arr1;
delete ptr;
return 0;
}
int * insertionshot(int arr1[],int n)
{
for(int a = 1; a <= n -1 ;a++)
{
int b = a;
while(b > 0 && arr1[b] < arr1[b-1])
{
int temp;
temp = arr1[b-1];
arr1[b-1] = arr1[b];
arr1[b] = temp;
b--;
}
}
return arr1;
}
void BinarySearch( int a[],int value)
{
int min,max,middle;
min = 0;
int ar[10];
for(int i =0;i < 10; i++)
{
ar[i] = a[i];
}
max = (sizeof(ar)/sizeof(ar[0]) -1);
middle = (min+max)/2;
while(min <= max)
{
if(ar[middle] == value)
{
cout << "The value found" << ar[middle];
break;
}
else if(ar[middle] < value)
{
min = middle +1;
}
else if(ar[middle] > value)
{
max = middle-1;
}
middle = (min+max)/2;
}
}
You're missing the most important part of a binary search: The collection you search in must be sorted.
For binary search, the array should be arranged in ascending or descending order.
Here is some working code that implements a modified version of the Quicksort algorithm that uses Insertion Sort for array size n > 8. My test array isn't sorting exactly right, and I think it must be with my implementation of Insertionsort and Insert.
The general form of the recursive Insertionsort algorithm is:
void Insertionsort(int S[], int n)
{
if(n>1)
Insertionsort(S,n-1);
Insert(S,n-1);
}
void Insert(int *S, int k)
{
int key = S[k];
int j = k-1;
while(j>=0 && S[j] > key)
{
S[j+1] = S[j];
j--;
}
S[j+1] = key;
}
Here is my complete working code that does not sort quite exactly right:
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
int comparisons = 0;
int compare_qs_m3_ins[12];
// Function prototypes
int partition(int *S,int l, int u);
void exchange(int list[], int p, int q);
void Insert(int S[], int k);
void Insertionsort(int S[], int low, int hi);
void Quicksort_Insert_M3(int S[], int n, int p, int r);
int main()
{
srand (time(NULL));
// Declare all arrays used for testing
int S1_500[500];
int S2_500[500];
int S3_500[500];
int S1_300[300];
int S2_300[300];
int S3_300[300];
int S1_100[100];
int S2_100[100];
int S3_100[100];
int S1_8[8];
int S2_8[8];
int S3_8[8];
// Fill arrays with random integers
for(int i=0; i<500; i++)
{
S1_500[i] = rand()%1000;
S2_500[i] = rand()%1000;
S3_500[i] = rand()%1000;
}
for(int i=0; i<300; i++)
{
S1_300[i] = rand()%1000;
S2_300[i] = rand()%1000;
S3_300[i] = rand()%1000;
}
for(int i=0; i<100; i++)
{
S1_100[i] = rand()%500;
S2_100[i] = rand()%500;
S3_100[i] = rand()%500;
}
for(int i=0; i<8; i++)
{
S1_8[i] = rand()%100;
S2_8[i] = rand()%100;
S3_8[i] = rand()%100;
}
Quicksort_Insert_M3(S1_500,500,0,499);
compare_qs_m3_ins[0] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S2_500,500,0,499);
compare_qs_m3_ins[1] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S3_500,500,0,499);
compare_qs_m3_ins[2] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S1_300,300,0,299);
compare_qs_m3_ins[3] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S2_300,300,0,299);
compare_qs_m3_ins[4] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S3_300,300,0,299);
compare_qs_m3_ins[5] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S1_100,100,0,99);
compare_qs_m3_ins[6] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S2_100,100,0,99);
compare_qs_m3_ins[7] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S3_100,100,0,99);
compare_qs_m3_ins[8] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S1_8,8,0,7);
compare_qs_m3_ins[9] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S2_8,8,0,7);
compare_qs_m3_ins[10] = comparisons;
comparisons = 0;
Quicksort_Insert_M3(S3_8,8,0,7);
compare_qs_m3_ins[11] = comparisons;
comparisons = 0;
//for(int i=0; i<12; i++)
//cout << compare_qs_m3_ins[i] << endl;
for(int i=0;i<499;i++)
cout << S1_500[i] << endl;
}
int partition(int *S,int l, int u)
{
int x = S[l];
int j = l;
for(int i=l+1; i<=u; i++)
{
comparisons++;
if(S[i] < x)
{
j++;
swap(S[i],S[j]);
}
}
int p = j;
swap(S[l],S[p]);
return p;
}
void swap(int &val1, int &val2)
{
int temp = val1;
val1 = val2;
val2 = temp;
}
void exchange(int list[], int p, int q)
{
int temp = list[p];
list[p] = list[q];
list[q] = temp;
}
int Sort3(int list[], int p, int r)
{
int median = (p + r) / 2;
comparisons++;
if(list[p] <= list[median])
{
comparisons++;
if(list[median]>list[r])
{
comparisons++;
if(list[p]<list[r])
{
int temp = list[p];
list[p] = list[r];
list[r] = list[median];
list[median] = temp;
}
else
{
exchange(list,median,r);
}
}
else
;
}
else
{
comparisons++;
if(list[p] > list[r])
{
comparisons++;
if(list[median] < list[r])
{
int temp = list[p];
list[p] = list[median];
list[median] = list[r];
list[r] = temp;
}
else
{
exchange(list,p,r);
}
}
else
{
exchange(list,p,median);
}
}
return list[r];
}
void Insert(int *S, int k)
{
int key = S[k];
int j = k-1;
while(j>=0 && S[j] > key)
{
S[j+1] = S[j];
j--;
comparisons++;
}
comparisons++;
S[j+1] = key;
}
void Insertionsort(int S[], int low, int hi)
{
if((hi-low)+1>1)
Insertionsort(S,low+1,hi);
Insert(S,hi-low);
}
void Quicksort_Insert_M3(int S[], int n, int low, int hi)
{
if((hi-low)<=8)
Insertionsort(S,low,hi);
else
{
if(low < hi)
{
if((low+1) == hi)
{
comparisons++;
if(S[low] > S[hi])
swap(S[low],S[hi]);
}
else
{
Sort3(S,low,hi);
if((low+2)<hi)
{
swap(S[low+1],S[(low+hi)/2]);
int q = partition(S, low+1, hi-1);
Quicksort_Insert_M3(S, n, low, q-1);
Quicksort_Insert_M3(S, n, q+1, hi);
}
}
}
}
}
The function supposed to sort three array elements in ascending order doesn't:
int Sort3(int list[], int p, int r)
{
called only for p + 2 <= r, so
int median = (p + r) / 2;
p < median < r here. Let a = list[p], b = list[median] and c = list[r].
comparisons++;
if(list[p] <= list[median])
{
comparisons++;
if(list[median]>list[r])
{
comparisons++;
if(list[p]<list[r])
{
So here we have a <= b, c < b and a < c, together a < c < b
int temp = list[p];
list[p] = list[r];
list[r] = list[median];
list[median] = temp;
but you place them in order c, a, b. Probably you intended to use if (list[r] < list[p]) there.
}
else
c <= a <= b
{
exchange(list,median,r);
so that arranges them in order a, c, b.
}
}
else
;
}
else
Here, b < a.
{
comparisons++;
if(list[p] > list[r])
{
c < a
comparisons++;
if(list[median] < list[r])
{
Then b < c < a
int temp = list[p];
list[p] = list[median];
list[median] = list[r];
list[r] = temp;
Yup, that's correct.
}
else
c <= b < a
{
exchange(list,p,r);
}
Okedoke.
}
else
{
b < a <= c
exchange(list,p,median);
Okay.
}
}
return list[r];
}
Why does this function return anything? You don't use the return value anyway.
"The general form of the recursive Insertionsort algorithm is" - if you need to have a head-recursive algorithm, yes, otherwise a better version is:
void Insertionsort(int S[], int i, int n)
{
Insert(S, i, n);
if(i < n)
Insertionsort(S, i+1, n);
}
which is much more understandable. Also, you might as well have put the body of Insert into Insertionsort.
I'm not going to try and figure out your overly complicated version of quicksort. A decent quicksort is around 20 lines or less (like this - www.algolist.net/Algorithms/Sorting/Quicksort) (and add another 10 or less for insertion sort). I suggest getting a better understanding by looking at another implementation and rewriting yours.
I believe this could've been asked as an extension of your previous question.