What's wrong in this "mergeSort"? - java

There's a mergeSort code that I copied at class lesson, can you help me to find the errors?
When I run the main that use mergeSort the program enters in an infinite loop but doesn't display any error. I tried to run in debug mode but I am not very expert and I don't find what's wrong. However I think that the error is in mergeSort(int[] v, int inf, int sup) recursion.
public class CopyOfSortMethods {
private static void merge(int[] v, int inf, int med, int sup) {
int aux[] = new int[v.length];
int i = inf;
int j = med + 1;
int k = inf;
while ((i <= med) && (j <= sup)) {
if (v[i] < v[j]) {
aux[k] = v[i];
i++;
k++;
} else {
aux[k] = v[j];
j++;
k++;
}
}
while (i <= med) {
aux[k] = v[i];
i++;
k++;
}
while (j <= sup) {
aux[k] = v[j];
j++;
k++;
}
for (i = 0; i <= sup; i++) {
v[i] = aux[i];
}
}
public static void mergeSort(int[] v, int inf, int sup) {
int med;
while (inf < sup){
med = (inf + sup)/2;
mergeSort(v, inf, med);
mergeSort(v, med + 1, sup);
merge(v, inf, med, sup);
}
}
public static void mergeSort(int[] v) {
if(v!=null) {
mergeSort(v, 0, v.length - 1);
}
}
}

As Maverik points out, the issue is the while loop in mergeSort().
inf and sup are never modified, so inf is always less than sup. The loop never terminates.

The problems in your merge sort (based in the comments):
In mergeSort method, you're recursively calling the mergeSort inside a while loop and never changing the values of inf and sup. Change this for an if instead.
if (inf < sup) {
//code goes here...
}
In your merge sort, at the bottom of the method body, you're moving the items all the items from aux array to v array. You should only move the elements between inf and sup:
//for (i = 0; i <= sup; i++) {
for (i = inf; i <= sup; i++) {
//code goes here...
}

Related

Trying to parallelize quicksort to run on multiple threads in Java

I have a quicksort algorithm that works fine, but when I try an parallelize it only the second half the array is being sorted, the other half is almost unchanged. And since I am new to parallel programming I have no idea why.
The solution I have is combined from different codes found online.
How do improve it so that he whole array is sorted?
public class foo {
private static final int N_THREADS = Runtime.getRuntime().availableProcessors();
private static final int FALLBACK = 2;
private static Executor pool = Executors.newFixedThreadPool(N_THREADS);
public static <T extends Comparable<T>> void sort(int[] numberArray){
if(numberArray == null && numberArray.length == 0){
return;
}
final AtomicInteger count = new AtomicInteger(1);
pool.execute(new QuicksortRunnable<T>(numberArray, 0, numberArray.length-1, count));
}
private static class QuicksortRunnable<T extends Comparable<T>> implements Runnable {
private final int[] values;
private final int left;
private final int right;
private final AtomicInteger count;
public QuicksortRunnable(int[] values, int left, int right, AtomicInteger count) {
this.values = values;
this.left = left;
this.right = right;
this.count = count;
}
#Override
public void run() {
quicksort(left, right);
synchronized (count) {
if (count.getAndDecrement() == 1)
count.notify();
}
}
private void quicksort(int pLeft, int pRight) {
int pivotIndex = (pRight - pLeft) / 2 + pLeft;
int pivot = values[pivotIndex];
int j = pRight;
int i = pLeft;
while (i < j) {
while (values[i] > pivot) {
i++;
}
while (values[j] < pivot) {
j--;
}
if (i <= j) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
i++;
j--;
}
}
if (count.get() >= FALLBACK * N_THREADS) {
if (pLeft < j)
quicksort(pLeft, j);
if (i < pRight)
quicksort(i, pRight);
} else {
if (pLeft < j) {
count.getAndAdd(1);
pool.execute(new QuicksortRunnable<T>(values, pLeft, j, count));
}
if (i < pRight) {
count.getAndAdd(1);
pool.execute(new QuicksortRunnable<T>(values, i, pRight, count));
}
}
}
}
~~~
My main function:
public static void main(String[] arg) {
Random rand = new Random();
int length = 1000;
int[] toSort = new int[length];
for(int i = 0; i<length; i++){
toSort[i] = rand.nextInt(length);
}
sort(toSort);
boolean sortedFH = true;
boolean sortedSH = true;
for(int i = 0; i<length/2; i++) {
if (toSort[i] < toSort[i + 1]) {
sortedFH = false;
}
}
for(int i = length/2; i<length-1; i++) {
if (toSort[i] < toSort[i + 1]) {
sortedSH = false;
}
}
System.out.println();
System.out.println("First half :" + sortedFH);
System.out.println("Second half :" + sortedSH);
}
}
Returns:
First half :false
Second half :true
EDIT: Removed a part of the program. I tried something, didn't work, forgot to remove it when posting the question.
Firstly I think the results you are seeing are mainly because you are printing out the results before the sorting threads have finished. You need to wait for all the threads to complete before you check the results.
Based on your code, you can do this easily enough using your AtomicInteger count to block the sort() returning until all the threads have finished.
public static <T extends Comparable<T>> void sort(int[] numberArray) {
if (numberArray == null || numberArray.length == 0) {
return;
}
final AtomicInteger count = new AtomicInteger(1);
pool.execute(new QuicksortRunnable<T>(numberArray, 0, numberArray.length - 1, count));
while (count.get() > 0) {
synchronized (count) {
count.wait();
}
}
}
As an aside, unless it is intentional, your algorithm looks like it is going to sort the array in descending order. I think you need to flip
while (values[i] > pivot) {
i++;
}
while (values[j] < pivot) {
j--;
}
to
while (values[i] < pivot) {
i++;
}
while (values[j] > pivot) {
j--;
}
The same applies to your checks at the end of the main method.
Your check on a null or empty array should be separated by an OR not an AND
if (numberArray == null || numberArray.length == 0) {
return;
}

using comparable in java for Bubble up in MaxHeap

I am trying to insert in a maxHeap in java and then bubble up the object. This is what I have done, I am not sure how I should approach the bubble up method.
I do understand the algorithm behind bubble up, which is as follows:
get parent node
see if L_childNode is less than parent Node. If Yes, then swap parent with L_child.
see if R_childNode is less than parent Node. If Yes, then swap parent with L_child.
Please point out what am I doing wrong?
private int getLeftChild(int n){
return x*2+1;
}
private int getRightChild(int n){
return x*2+2;
}
public void insert (E item) {
//Integer pos_lastEl= new Integer (heapArray.lastElement());
heapArray.add(item);
bubbleUp(item);
}
//To use to reheap up when item inserted at end of heap (complete tree)
private void bubbleUp(E x){
int place = heapArray.size()-1;
int parent=(place-1)/2;
if ((parent>=0) && (parent.compareTo(heapArray.get(getLeftChild))<0)){
swap(place,parent);
}else ((parent>=0 && (parent.compareTo(heapArray.get(getRightChild))<0))){
swap(place,parent);
}
}
//swaps two objects at index i and j
private void swap(int i, int j){
int max=heapArray.size();
if(i>=0 && i<max && j>=0 && j<max){
E temp=heapArray.get(i);
//put J item in I
heapArray.set(i,heapArray.get(j));
heapArray.set(j,temp);
}
}
Your major problem is using if instead of while to bubble up the newly added element to the proper position.
And there are also some other issues in your code, sorry I had to do some refactoring to make it clean enough:
public class MaxHeapTest<E extends Comparable<E>> {
List<E> heapArray = new ArrayList<>();
public static void main(String... args) {
int N = 13;
MaxHeapTest<Integer> maxHeap = new MaxHeapTest();
for (int i = 0; i < N; ++i) { // ascending;
maxHeap.insert(i);
}
while (!maxHeap.isEmpty()) { // descending now;
System.out.print(maxHeap.delMax() + " ");
}
}
public E delMax() {
E e = heapArray.get(0);
swap(0, heapArray.size() - 1);
heapArray.remove(heapArray.size() - 1);
sinkDown(0);
return e;
}
public void insert(E item) {
heapArray.add(item);
bubbleUp(item);
}
public boolean isEmpty() {
return heapArray.isEmpty();
}
private void bubbleUp(E x) {
int k = heapArray.indexOf(x);
int j = (k - 1) / 2;
while (j >= 0) {
if (heapArray.get(j).compareTo(heapArray.get(k)) < 0) {
swap(k, j);
k = j;
j = (j - 1) / 2;
} else break;
}
}
private void sinkDown(int k) {
int j = 2 * k + 1;
while (j < heapArray.size()) {
if (j < heapArray.size() - 1 && heapArray.get(j).compareTo(heapArray.get(j + 1)) < 0) j++;
if (heapArray.get(k).compareTo(heapArray.get(j)) < 0) {
swap(k, j);
k = j;
j = 2 * j + 1;
} else break;
}
}
private void swap(int i, int j) {
E temp = heapArray.get(i);
heapArray.set(i, heapArray.get(j));
heapArray.set(j, temp);
}
}
After the maxHeap, we can easily output the descending numbers as:
12 11 10 9 8 7 6 5 4 3 2 1 0

Bin Packing(Searched quad groups for answers)

I am writing a bin packing program in one dimension. I want only one possible bin. So it does not include a lot of bin its only one. This program is only searching quad groups and explode if quad groups are not equal to the searching number. I want to search every possible group that is bigger than quads.
In example we have 60 60 50 40 45 35 25 15 and we are looking for summing equal to 180 and answer is 60 60 45 15 that's fine but if we search 250 it will not working.
Can you help me?
That's the link for program https://github.com/omerbguclu/BinPacking1D
That's the code for the algorithm o array is the numbers, a array is the location of answers
public BinPacking() {
}
public void binpack(ArrayList<Integer> o, ArrayList<Integer> a, int wanted) {
int sum = 0;
if (wanted > 0) {
control(o, a, wanted);
if (is) {
return;
}
for (int i = 0; i < o.size(); i++) {
sum += o.get(i);
summing(o, a, wanted - sum, i + 1);
if (is) {
a.add(i);
return;
}
for (int j = i; j < o.size(); j++) {
if (i != j) {
sum += o.get(j);
summing(o, a, wanted - sum, j + 1);
if (is) {
a.add(i);
a.add(j);
return;
}
sum -= o.get(j);
}
}
sum -= o.get(i);
// "/////////////*******************////////////////////");
}
if (wanted != sum) {
System.out.println("There is not an answer with quad summing method");
}
}
}
public void summing(ArrayList<Integer> o, ArrayList<Integer> a, int wanted, int loop) {
int sum = 0;
if (loop < o.size() && wanted > 0) {
for (int i = loop; i < o.size(); i++) {
if (wanted == o.get(i)) {
a.add(i);
is = true;
return;
}
for (int j = loop; j < o.size(); j++) {
if (i != j) {
sum = o.get(i) + o.get(j);
if (wanted != sum) {
sum = 0;
} else {
a.add(i);
a.add(j);
is = true;
return;
}
}
// System.out.println("///////////////////////////////////");
}
}
System.out.println("There is not an answer with binary summing method");
}
}
public void control(ArrayList<Integer> o, ArrayList<Integer> a, int wanted) {
for (int i = 0; i < o.size(); i++) {
if (o.get(i) == wanted) {
a.add(i);
is = true;
break;
}
}
}
There is a pretty well established and efficient mechanism for getting every possible combination of a set of objects. Essentially you treat membership of the combination as a BitSet which represents whether each member of the set is in the combination. Then visiting every combination is just visiting every BitSet combination.
Here's how I tend to implement it:
public class Combo<T> implements Iterable<List<T>> {
private final List<T> set;
public Combo(List<T> set) {
this.set = set;
}
public Iterator<List<T>> iterator() {
BitSet combo = new BitSet(set.size());
return new Iterator<List<T>>() {
public boolean hasNext() {
return combo.cardinality() < set.size();
}
public List<T> next() {
int i = 0;
while (combo.get(i))
combo.clear(i++);
combo.set(i);
return combo.stream().mapToObj(set::get).collect(Collectors.toList());
}
};
}
}
So your solution would become:
for (List<Integer> combo: new Combo<>(...)) {
if (combo.size >= 4 && combo.stream.reduce(0, Integer::sum) == total)
....
}
A hackier version of the same idea would be:
for (long l = 0; l < 1 << (input.size() - 1); l++) {
List<Integer> combo = BitSet.valueOf(new long[]{l}).stream()
.mapToObj(input::get).collect(Collectors.toList());
if (combo.stream().mapToInt(n -> n).sum() == total) {
System.out.println(combo);
}
}

Insertion sort, number of comparisons

Hi all for an assignment we must count the number of comparisons for a number of algorithms. I'm using the code in the book "Algorithms" by Sedgewick & Wayne. I don't see where my code is wrong actually... As soon we going to compare something I count my comparison...
public long sort(Comparable[] a) {
if (a == null) {
throw new IllegalArgumentException("argument 'array' must not be null.");
}
int N = a.length;
for (int i = 0; i < N; i++) {
for (int j = i; j > 0; j--) {
this.comparisons++;
if(less(a[j], a[j-1]))
exch(a, j, j-1);
}
assert isSorted(a, 0, i);
}
assert isSorted(a);
return this.comparisons;
}
the less method which I use:
private boolean less(Comparable v, Comparable w) {
return (v.compareTo(w) < 0);
}
It must pass this test
Integer[] array = {4, 2, 1, 3, -1};
Comparable[] arrayClone1 = array.clone();
Comparable[] arrayClone2 = array.clone();
long nbCompares1 = i.sort(arrayClone1);
long nbCompares2 = i.sort(arrayClone2);
System.out.println("1" + nbCompares1);
System.out.println("2" + nbCompares2);
those two should be equal....
The isSorted methods:
private boolean isSorted(Comparable[] a) {
System.out.println("here");
return isSorted(a, 0, a.length - 1);
}
// is the array sorted from a[lo] to a[hi]
private boolean isSorted(Comparable[] a, int lo, int hi) {
System.out.println("here1");
for (int i = lo + 1; i <= hi; i++)
if (less(a[i], a[i-1])) return false;
return true;
}
Someone ideas about this? Help will be appreciated!
Number of comparisons should be exactly N*(N-1)/2. Maybe you mess with comparisons field in somewhere else, so I would advise to use local variable instead:
public long sort(Comparable[] a) {
if (a == null) {
throw new IllegalArgumentException("argument 'array' must not be null.");
}
int N = a.length;
int comparisonsCount = 0; // use this instead
for (int i = 0; i < N; i++) {
for (int j = i; j > 0; j--) {
comparisonsCount++; // edit here
if(less(a[j], a[j-1]))
exch(a, j, j-1);
}
assert isSorted(a, 0, i);
}
assert isSorted(a);
return comparisonsCount; // and here
}

Array Out Of Bounds

The purpose of this program is to find the kth smallest element in an array without sorting the array using a recursive and nonrecursive decrease and conquer type method.
I was hoping someone could look over my code and try to help me with my array out of bounds error(s).
The method that is throwing these errors is the recursive selection the non recursive selection works fine.
My driver is also attached and everything should compile if you want to test my code.
public class KthSmallest
{
private int counter;
private int term;
private int[] A;
int SelectionNonRecursive(int A[], int kthSmallest, int sizeOfA)
{
this.A = A;
if(kthSmallest == 1 || kthSmallest == sizeOfA)
{
return (LinearSearch(kthSmallest, sizeOfA));
}
else
{
for(int i = 0; i<sizeOfA; i++)
{
counter = 0;
for(int j = 0; j<sizeOfA; j++)
{
if(A[i] < A[j])
{
counter++;
}
}
if((sizeOfA - counter) == kthSmallest)
{
return A[i];
}
}
}
return 0;
}
int SelectionRecursive(int A[], int kthSmallest, int sizeOfA)
{
this.A = A;
return Selection_R(0, sizeOfA - 1, kthSmallest);
}
int Selection_R(int l, int r, int kthSmallest)
{
if(l<r)
{
if(kthSmallest == 1 || kthSmallest == A.length)
{
return (LinearSearch(kthSmallest, A.length));
}
else
{
int s = LomutoPartition(l, r);
if(s == kthSmallest - 1)
{
return A[s];
}
else if(s > (A[0] + kthSmallest - 1))
{
Selection_R(l, s-1, kthSmallest);
}
else
{
Selection_R(s+1, r, kthSmallest);
}
}
}
return 0;
}
int LomutoPartition(int l, int r)
{
int pivot = A[l];
int s = l;
for(int i = l+1; i<r; i++)
{
if(A[i] < pivot)
{
s += 1;
swap(A[s], A[i]);
}
}
swap(A[l], A[s]);
return s;
}
public void swap(int i, int j)
{
int holder = A[i];
A[i] = A[j];
A[j] = holder;
}
int LinearSearch(int kthSmallest, int sizeOfA)
{
term = A[0];
for(int i=1; i<sizeOfA; i++)
{
if(kthSmallest == 1)
{
if(term > A[i])
{
term = A[i];
}
}
else
{
if(term < A[i])
{
term = A[i];
}
}
}
return term;
}
}
public class KthDriver
{
public static void main(String[] args)
{
KthSmallest k1 = new KthSmallest();
int[] array = {7,1,5,9,3};
System.out.print(k1.SelectionRecursive(array, 3, array.length));
}
}
Inside your LomutoPartition method, you are passing the array elements in your swap method: -
swap(A[s], A[i]); // Inside for loop
and
swap(A[l], A[s]); // Outside for loop
And your swap method considers them as indices: -
public void swap(int i, int j) <-- // `i` and `j` are elements A[s] and A[i]
{
int holder = A[i]; <-- // You are accessing them as indices(A[i] -> A[A[s]])
A[i] = A[j];
A[j] = holder;
}
That is why you are getting that exception. Because, if any element in array is greater than size, it will blast out.
You should change your invocation to: -
swap(s, i); // Inside for loop
and
swap(l, s); // Outside for loop
respectively. And leave your method as it is.
Note that, you should pass array indices, and not array elements. If you pass array elements, then the swapping in the method will not be reflected in your array. Because, your method will have its own copy of your elements.

Categories

Resources