What corrections should I make to the following MaxHeap Implementation in Java?The Insert function keeps running when called. What is the error in the Insert and the BuildHeap functions?I have edited the PercolateDown function. I think it should be correct now..?
public class MaxHeap {
public int[] array;
public int count;
public int capacity;
public MaxHeap(int capacity){
this.capacity=capacity;
this.count=0;
this.array=new int[capacity];
}
public int Parent(int i){
if(i<=0 || i>=this.count)
return -1;
return
(i-1)/2;
}
public int LeftChild(int i){
int left=2*i+1;
if(left>=this.count)
return -1;
return left;
}
public int RightChild(int i){
int right=2*i+2;
if(right>=this.count)
return -1;
return right;
}
public int GetMaximum(){
if(this.count==0)
return -1;
return this.array[0];
}
public void PercolateDown(int i){
int l,r,max,temp;
l=LeftChild(i);
r=RightChild(i);
if(l!=-1 && this.array[l]>this.array[i])
max=l;
else
max=i;
if(r!=-1 && this.array[r]>this.array[max])
max=r;
if(max!=i){
temp=this.array[i];
this.array[i]=this.array[max];
this.array[max]=temp;
}
if(max==i){return;}
PercolateDown(max);
}
public int DeleteMax(){
if(this.count==0)
return -1;
int data=this.array[0];
this.array[0]=this.array[this.count-1];
this.count--;
PercolateDown(0);
return data;
}
public void Insert(int data){
int i;
if(this.count==this.capacity){
ResizeHeap();
}
this.count++;
i=this.count-1;
while(i>=0 && data>this.array[(i-1)/2]){
this.array[i]=this.array[(i-1)/2];
i=(i-1)/2;
}
this.array[i]=data;
}
public void ResizeHeap(){
int[] array_old=new int[this.capacity];
for(int i=0;i<this.capacity;i++){
array_old[i]=this.array[i];
}
this.array=new int[this.capacity*2];
for(int i=0;i<this.capacity;i++){
this.array[i]=array_old[i];
}
this.capacity*=2;
array_old=null;
}
public static MaxHeap BuildHeap(int[]A,int n){
MaxHeap h=new MaxHeap(n*2);
if(A==null)return h;
//while(n>h.capacity)
//h.ResizeHeap();
h.capacity=n*2;
for(int i=0;i<n;i++){
h.array[i]=A[i];
}
h.count=n;
for(int i=(n/2)-1;i>=0;i++){
h.PercolateDown(i);
}
return h;
}
public void Delete(int i){
if(this.count<i){
System.out.println("Wrong Position");
return;
}
this.array[i]=this.array[this.count-1];
this.count--;
PercolateDown(i);
}
public static void main(String[] args){
//int[] A={7,6,5,4,3,2,1};
//int len=A.length;
//MaxHeap h=BuildHeap(A,len);
//for(int i=0;i<len;i++){
//System.out.print(h.array[i]+" ");
//}
MaxHeap h=new MaxHeap(10);
h.Insert(7);
System.out.print(h.array[0]);
}
}
I inserted this statement inside the while loop in Insert():
System.out.println(i);
It prints 0 every time. Since 0 >= 0 and also your array comes with 0s in it, so when data is 7 and 7 > 0, the while condition is true. Inside your loop you are setting i to (i - 1) / 2, this is -1 / 2, which is rounded towards zero, yielding 0 again. So i is not changed, and your while condition continues to be true. This is why your loop never stops. I have not understood how you had intended the method to work, so I dare not give suggestions.
Trying the same print statement inside the for loop of BuildHeap() reveals that i is ever increasing until it overflows and suddenly is negative (if you add one to the highest int you can have, you get the lowest possible negative value, -2147483648). I think you had intended i-- rather then i++ in for(int i=(n/2)-1;i>=0;i++){.
Related
I've got a task that gets an int value "n" and an Int Array as parameters and is supposed to return a boolean.
The method is supposed to determine, how many "n" are in the given Array. If the number is even the method should return true, else false. If the Array has the length 0, it should return "false" aswell.
What i managed to do is :
public static boolean evenNumberOf(int n, int[] arr) {
boolean result = false;
System.out.println("Starting count");
if (n < arr.length) {
if (arr[n] == n) {
result = true;
} else {
return evenNumberOf(n - 1, arr);
}
}
return result;
}
Im just really confused and i dont know what to do to be honest. I have really tried my best but the longer i work on this task the less i understand.
Any help is appreciated and thank you in advance! :)
Separate it into two methods:
The method you call initially
and a method that gets called recursively to count the number of ns in the array:
boolean evenNumberOf(int n, int[] arr) {
int count = countNs(n, arr, 0);
// Logic to choose what to return based on count and/or length of arr.
}
int countNs(int n, int[] arr, int i) {
// Check if arr[i] is equal to n.
// Make a recursive call to countNs for i := i + 1.
// Combine the check/recursive call result to return a value.
}
Try
//arr should not be empty, index and count >= 0
public static boolean evenNumberOf(int value, int index,int[]arr, int count) {
if(index >= arr.length) return count%2 == 0;
if(arr[index] == value ) {
count++;
}
return evenNumberOf(value, ++index, arr, count);
}
Usage example: System.out.println(evenNumberOf(2, 0, new int[]{2,0,3,7,6,11,1,2}, 0));
(You can add an helper method evenNumberOf(int value,int[]arr))
as Recursive Counting in an Array got closed as a duplicate I will answer it here:
Let's analyze what you did and why it's wrong
public static int countN(int n,int [] arr,int i, int count) {
if (arr[i] == n) {
System.out.println("MATCH");
count++;
return count;
}
Here you already return the count when you get a match. You shouldn't do that because if the first number is already the same it returns 1. all you need to do is increase the count here
else {
System.out.println("Moving on");
i = i + 1;
countN(n,arr,i, count);
}
Here you do the recursion. This is good. But this also needs to be done in the case that you do get a match. And it needs to return that value. But, also this only needs to be done when you are not at the end of the array yet
if (arr.length == i) {
evenNumberOf(n,arr);
}
this part doesn't make sense, because you call evenNumberOf with the exact same arguments as it started so it will result in an infinite loop. you should have returned the count here. also keep in mind that the last index of an array is length - 1
putting this together you can make:
public static int countN(int n,int [] arr,int i, int count) {
if (arr[i] == n) {
count++;
}
if (arr.length - 1 == i) {
return count;
}
return countN(n, arr, i + 1, count);
}
For training purposes I tried to code a program which counts how often a given number appears in an given array of integers. Then checks if the number is even or odd. Without using any imports or loops. I tried to solve it recursive.
For Example:
(3, new int[]{3,3,4,5,3,3,2,1})
There are 4 threes, so the Program should check if 4 is even or odd.
After days of coding and not working code I decided to ask here:
any Solutions?
public static int evenNumberOf(int num, int[] numarr) {
int i = 0 ;
int counter = 0;
if(a == null || a.length == 0) {
return false;
} else {
if(a[i] == a.length -1 ) {
if(counter % 2 == 0) {
System.out.println("true");
return true;
} else System.out.println("false");
return false;
} else {
if(a[i] == n) {
counter++;
i++;
return evenNumberOf(n,a) ;
} else {
i++;
return evenNumberOf(n,a) ;
Hint:
If you are trying to do this recursively, you can do this quickly with divide and conquer. Split the array into half, count each subarray and combine the results. Make sure the base case of an empty array/single element array is handled correctly.
Try this:
public static void main(String[] args) throws Exception{
System.out.println(evenNumberOf(2, 0, new int[]{2,0,3,7,6,11,1,2}, 0));
}
//arr should not be empty, index and count >= 0
public static int evenNumberOf(int num, int index,int[]numarr, int count) {
if(index >= numarr.length) return count;
if(numarr[index] == num ) {
count++;
}
return evenNumberOf(num, ++index, numarr, count);
}
You can add an helper method to make calling simpler :
public static int evenNumberOf(int num, int[] numarr) {
return evenNumberOf(num, 0, numarr,0);
}
while running above code the first pivot is returned as 3.This pivot is transmitted as 2 in first recursion method but in second recursion it does not take value 4. can some one identify what is problem.
class QuickSortRevision{
int pivot;
void QuickSort(int[] arr,int low,int high){
if(low>=high)
return;
pivot = quickSortPivot(arr,low,high);//first execution pivot =3
QuickSort(arr,low,pivot-1);//this is taking 0,2 as parameter;
QuickSort(arr,pivot+1,high);//but this is not taking 4,8 as parameter;
}
int quickSortPivot(int[] arr,int low,int high){
int temp,index,partition,lindex,hindex;
lindex=low;
hindex=high-1;
partition = arr[high];
index=high;
System.out.println("low : "+low+" high "+high);
while(lindex!=hindex){
while(arr[lindex]<partition && (lindex!=hindex) ){
lindex++;
}
while(arr[hindex]>partition && (lindex!=hindex) ){
hindex--;
}
if( lindex!=hindex)
{
temp=arr[lindex];
arr[lindex]=arr[hindex];
arr[hindex]=temp;
lindex++;hindex--;
}
}
temp=arr[lindex];
arr[lindex]=partition;
arr[index]=temp;
System.out.println("lindex: "+lindex);
return lindex;
}
void printArray(int[] arr)
{
for(int element : arr)
System.out.print(" "+element);
}
public static void main(String[] args){
QuickSortRevision qs = new QuickSortRevision();
int arr[]={17,41,5,22,54,6,29,3,13};
qs.QuickSort(arr,0,arr.length-1);
qs.printArray(arr);
}}
The first time you call QuickSort the class member pivotis assigned the value 3. Then a recursive call to QuickSort invokes quickSortPivot whose result is assigned to pivot (and further recursive calls also modify this value). When this call to Quicksort returns, the value of pivothas been modified!
You shoud declre pivot as a variable of the method QuickSort, not an instance variable of the class QuickSortRevision
PS: the function QuickSort should be called quickSort
replace you code lindex!=hindex to lindex<=hindex.
because there a sence like lindex > hindex.
The code like this:
public class QuickSortRevision{
int pivot;
static int id = 1;
void QuickSort(int[] arr,int low,int high){
if(low>=high)
return;
pivot = quickSortPivot(arr,low,high);//first execution pivot =3
QuickSort(arr,low,pivot-1);//this is taking 0,2 as parameter;
QuickSort(arr,pivot+1,high);//but this is not taking 4,8 as parameter;
}
int quickSortPivot(int[] arr,int low,int high){
int temp,index,partition,lindex,hindex;
lindex=low;
hindex=high - 1;
partition = arr[high];
index=high;
while(lindex <= hindex){
while(arr[lindex]<partition && (lindex<=hindex) ){
lindex++;
}
while(arr[hindex]>partition && (lindex<=hindex) ){
hindex--;
}
System.out.println("low : "+low+" high "+high);
if( lindex<=hindex)
{
temp=arr[lindex];
arr[lindex]=arr[hindex];
arr[hindex]=temp;
lindex++;hindex--;
}
}
temp=arr[lindex];
arr[lindex]=partition;
arr[index]=temp;
// System.out.println(lindex+" "+arr[lindex]);
System.out.println("lindex: "+lindex);
return lindex;
}
void printArray(int[] arr)
{
for(int element : arr)
System.out.print(" "+element);
}
public static void main(String[] args){
QuickSortRevision qs = new QuickSortRevision();
int arr[]={17,41,5,22,54,6,29,3,13};
qs.QuickSort(arr,0,arr.length-1);
qs.printArray(arr);
}
}
This question already has answers here:
What's the simplest way to print a Java array?
(37 answers)
Closed 8 years ago.
[after edit 1] I have seen the other answers here in SO, and from looking at my code, I find that I am adhering to the principle of Java's pass-by-value-of-reference. But still my array is not getting sorted. Please can someone point out any errors I am making in my code?
[after edit 2] Found the problem. It was nothing to do with array passing. In my merge method, it should be if (end-start<=0) not the other way round!
I am trying to implement mergesort. However, I am unable to display values of my array and am unsure of how to pass my arrays in Java such that the original array can be modified.
How can I modify my current code to display the values of the sorted array?
I understand java passes the copy of the array's reference around, but doesnt this mean that the original array gets modified?
CODE:
I am calling mergesort method from my main method.
public static void main(String[] args) {
int[] qn = {10,22,33,4,5,6,1};
qn= mergesort(qn,0,qn.length-1);
for (int i=0;i<qn.length;i++){ //print to see values if sorted/not
System.out.print(qn[i]+ " ");
}
}
public static int[] mergesort(int[] arr,int start,int end){
int mid = (end+start)/2;
if (end - start<=0){
return arr;
}
else if (end-start>=1){
arr=mergesort(arr,start,mid);
arr=mergesort(arr,mid+1,end);
}
arr=merge(arr,start,end);
for (int i=0;i<arr.length;i++){
System.out.print(arr[i]+ " ");
}
System.out.println();
return arr;
}
public static int[] merge(int[] arr,int start,int end){
int mid= (start+end)/2;
if(start-end<=0){
return arr;
}
int a= start; int b = mid+1;
while (a<=mid && b <=end){
if (arr[b]<arr[a]){
int tmp = arr[b++];
for(int i=++mid;i>a;i--){
arr[i]=arr[i-1];
}
arr[a++]=tmp;
}
else if (arr[b]>arr[a]){
a++;
}
else{ //arr[b]=arr[a]
if(a==mid && b == end){
break; //all between mid and end will be equal too
}
int tmp= arr[b++];
a++;
for (int i=++mid;i>a;i--){
arr[i]=arr[i-1];
}
arr[a++]=tmp;
//a++;
//b++;
}
}
return arr;
}
}
modified my answer based on Manu's below. but it's still not working. Attaching code below:
public static void mergesort(int[] arr,int start,int end){
int mid = (end+start)/2;
if (end - start<=0){
return;
}
else if (end-start>=1){
mergesort(arr,start,mid);
mergesort(arr,mid+1,end);
}
merge(arr,start,end);
for (int i=0;i<arr.length;i++){
System.out.print(arr[i]+ " ");
}
System.out.println();
return;
}
public static void merge(int[] arr,int start,int end){
int mid= (start+end)/2;
if(start-end<=0){
return;
}
int a= start; int b = mid+1;
while (a<=mid && b <=end){
if (arr[b]<arr[a]){
int tmp = arr[b++];
for(int i=++mid;i>a;i--){
arr[i]=arr[i-1];
}
arr[a++]=tmp;
}
else if (arr[b]>arr[a]){
a++;
}
else{ //arr[b]=arr[a]
if(a==mid && b == end){
break; //all between mid and end will be equal too (pearl)
}
int tmp= arr[b++];
a++;
for (int i=++mid;i>a;i--){
arr[i]=arr[i-1];
}
arr[a++]=tmp;
//a++;
//b++;
}
}
return;
}
}
You are right, in Java, the copy of the reference of the array gets passed to the function. However, both references point to the same object (the array in your case). This means if you change the values of the array in your merge-method, the values of the array in your mergesort-method changes too. Reqrite your code to this:
public static void mergesort(int[] arr, ...
public static void merge(int[] arr, ...
and simply call
merge(arr, start, mid);
I'm trying to implement QuickSort algorithm program in Java, but I'm getting incorrect answer.
public class QuickSort {
public static void main(String[] args){
int arr[]={12,34,22,64,34,33,23,64,33};
int i=0;
int j=arr.length;
while(i<j){
i=quickSort(arr,i,i+1,j-1);
}
for(i=0;i<arr.length;i++)
System.out.print(arr[i]+" ");
}
public static int quickSort(int arr[],int pivot,int i,int j){
if(i>j) {
swap(arr,pivot,j);
return i;
}
while(i<arr.length&&arr[i]<=arr[pivot]) {
i++;
}
while(j>=1&&arr[j]>=arr[pivot]) {
j--;
}
if(i<j)
swap(arr,i,j);
return quickSort(arr,pivot,i,j);
}
public static void swap(int[] arr,int i,int j) {
int temp;
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
The above program giving me the output as: 12 23 22 33 34 33 64 34 64
Could anyone please tell me how can I get my desire result?
The problem is that this is not really how quicksort works. Quicksort is a recursive algorithm that should only be called once from outside of itself. The idea is that at each iteration, you partition the array into two halves - the left half contains all elements less than the pivot, and the right half contains all elements greater than / equal to the pivot. Then you quicksort the two halves, and finally put the pivot in the middle.
If the side that you are quicksorting is less than 3 elements long, you can just swap the two elements or leave them, and that part of the array is done.
But it doesn't look like your code is doing that at all - you are calling Quicksort 6 times from your client, and within the quicksort function you are making at most one swap. So this is not a case where someone is going to be able to look at your code and debug it by telling you to move a swap or something. You need to revisit your logic.
Check out the Wikipedia diagram for a visual example of what is supposed to happen in a single iteration:
http://en.wikipedia.org/wiki/File:Partition_example.svg
There are open source implementations of quicksort in Apache Harmony and Apache Mahout, probably amongst many others. You can read them.
public static int partition(int[] a, int p, int r){
int i=p,j=r,pivot=a[r];
while(i<j){
while(i<r && a[i] <= pivot){
i++;
}
while(j>p && a[j]>pivot){
j--;
}
if(i<j){
swap(a, i, j);
}
}
return j;
}
public static void quickSort(int[] a, int p, int r){
if(p<r){
int q=partition(a, p, r);
if(p==q){
quickSort(a, p+1, r);
}else if(q==r){
quickSort(a, p, r-1);
}else {
quickSort(a, p, q);
quickSort(a, q+1, r);
}
}
}
public static void swap(int[] a, int p1, int p2){
int temp=a[p1];
a[p1]=a[p2];
a[p2]=temp;
}
here is a quicksort algorithm
package drawFramePackage;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Random;
public class QuicksortAlgorithm {
ArrayList<AffineTransform> affs;
ListIterator<AffineTransform> li;
Integer count, count2;
/**
* #param args
*/
public static void main(String[] args) {
new QuicksortAlgorithm();
}
public QuicksortAlgorithm(){
count = new Integer(0);
count2 = new Integer(1);
affs = new ArrayList<AffineTransform>();
for (int i = 0; i <= 128; i++){
affs.add(new AffineTransform(1, 0, 0, 1, new Random().nextInt(1024), 0));
}
affs = arrangeNumbers(affs);
printNumbers();
}
public ArrayList<AffineTransform> arrangeNumbers(ArrayList<AffineTransform> list){
while (list.size() > 1 && count != list.size() - 1){
if (list.get(count2).getTranslateX() > list.get(count).getTranslateX()){
list.add(count, list.get(count2));
list.remove(count2 + 1);
}
if (count2 == list.size() - 1){
count++;
count2 = count + 1;
}
else{
count2++;
}
}
return list;
}
public void printNumbers(){
li = affs.listIterator();
while (li.hasNext()){
System.out.println(li.next());
}
}
}
also available with description at nathan's computer knowledge with a description
[code]
[/code]
``
Your loop is not working properly. Refer the code which is solve your problem about Quick Sort
static void quickSort (int[] numbers, int low, int high)
{
int i=low;
int j=high;
int temp;
int middle=numbers[(low+high)/2];
while (i<j) {
while (numbers[i]<middle) {
i++;
}
while (numbers[j]>middle) {
j--;
}
if (i<=j) {
temp=numbers[i];
numbers[i]=numbers[j];
numbers[j]=temp;
i++;
j--;
}
}
if (low<j) {
quickSort(numbers, low, j);
}
if (i<high) {
quickSort(numbers, i, high);
}
}
Refer Quick sort.
Please find comprehensive working code for quick sort algorithm implemented in Java here,
http://tech.bragboy.com/2010/01/quick-sort-in-java.html