insertion sort and 2 d arrays - java

I'm trying to use insertion sort to sort a 2 d array in Java by the first column values of each row. I've tested it on an array of size 2 but when I try the code for size 3 it doesn't even run the for loop. Thank you for any help you can give.
public int[][] sortC(int[][] temp)
{
if (temp.length == 1)
{
return temp;
}
else if (temp.length >= 2)
{
for (int i = 1; i <= temp.length - 1; i++)
{
int holdRow = temp[i][0];
int holdCol = temp[i][1];
// hold past index
int holdRowP = temp[i - 1][0];
int holdColP = temp[i - 1][1];
int j = i;
while (j > 0 && holdRow < holdRowP)
{
holdRow = temp[j][0];
holdCol = temp[j][1];
// hold past index
holdRowP = temp[j - 1][0];
holdColP = temp[j - 1][1];
// make single swap
temp[j][0] = holdRowP;
temp[j][1] = holdColP;
temp[j-1][0] = holdRow;
temp[j-1][1] = holdCol;
j--;
}
}
}
return temp;
}

You can simplify alot and make it work for arbitrary size by using the fact that a Java 2D array is really an array of arrays. The internal arrays (i.e., the rows) can be moved around as whole units rather than piecemeal as you're doing.
As your code is modifying the passed argument, there's also no need to return the array.
After the call sortC(input), the input array will be sorted.
Using both of these, your code can be reduced to
public void sortC(int[][] temp)
{
if (temp.length >= 2)
{
for (int i = 1; i <= temp.length - 1; i++)
{
int[] hold = temp[i];
int[] holdP = temp[i-1];
int j = i;
while (j > 0 && hold[0] < holdP[0])
{
hold = temp[j];
holdP = temp[j-1];
temp[j] = holdP;
temp[j-1] = hold;
j--;
}
}
}
}

Related

How to reduce the number of loops if there is no change?

This code is radix sort in Java.
Now I can sort. But I want to reduce its functionality if there is no change in the
array, let it stop the loop and show the value.
Where do I have to fix it? Please guide me, thanks in advance.
public class RadixSort {
void countingSort(int inputArray[], int size, int place) {
//find largest element in input array at 'place'(unit,ten's etc)
int k = ((inputArray[0] / place) % 10);
for (int i = 1; i < size; i++) {
if (k < ((inputArray[i] / place) % 10)) {
k = ((inputArray[i] / place) % 10);
}
}
//initialize the count array of size (k+1) with all elements as 0.
int count[] = new int[k + 1];
for (int i = 0; i <= k; i++) {
count[i] = 0;
}
//Count the occurrence of each element of input array based on place value
//store the count at place value in count array.
for (int i = 0; i < size; i++) {
count[((inputArray[i] / place) % 10)]++;
}
//find cumulative(increased) sum in count array
for (int i = 1; i < (k + 1); i++) {
count[i] += count[i - 1];
}
//Store the elements from input array to output array using count array.
int outputArray[] = new int[size];
for (int j = (size - 1); j >= 0; j--) {
outputArray[count[((inputArray[j] / place) % 10)] - 1] = inputArray[j];
count[(inputArray[j] / place) % 10]--;//decrease count by one.
}
for (int i = 0; i < size; i++) {
inputArray[i] = outputArray[i];//copying output array to input array.
}
System.out.println(Arrays.toString(inputArray));
}
void radixSort(int inputArray[], int size) {
//find max element of inputArray
int max = inputArray[0];
for (int i = 1; i < size; i++) {
if (max < inputArray[i]) {
max = inputArray[i];
}
}
//find number of digits in max element
int d = 0;
while (max > 0) {
d++;
max /= 10;
}
//Use counting cort d no of times
int place = 1;//unit place
for (int i = 0; i < d; i++) {
System.out.print("iteration no = "+(i+1)+" ");
countingSort(inputArray, size, place);
place *= 10;//ten's , hundred's place etc
}
}
1
I'm going to resist typing out some code for you and instead go over the concepts since this looks like homework.
If I'm understanding you correctly, your problem boils down to: "I want to check if two arrays are equivalent and if they are, break out of a loop". Lets tackle the latter part first.
In Java, you can use the keyword"
break;
to break out of a loop.
A guide for checking if two arrays are equivalent in java can be found here:
https://www.geeksforgeeks.org/compare-two-arrays-java/
Sorry if this doesnt answer your question. Im just gonna suggest a faster way to find the digits of each element. Take the log base 10 of the element and add 1.
Like this : int digits = (int) Math.log10(i)+1;

Java Removing Redundant Items in Array

For this particular problem I am attempting to remove redundant elements in an sorted array and replace them all with 0s at the end of the array. For example, if I had an array consisting of the int elements
1,3,3,4,4,5,6,6,7
My output array should be
1,3,4,5,6,7,0,0,0
My first attempt at the problem was to create a swapper in order to push all the 0s to the end of the list after removing the elements, but it won't seem to push the zeros to the end of the list. Here is my code.
public void implode(int[] ary)
{
int swapper = -1;
int[] newARY = new int[ary.length];
int current = -1;
for (int i = 0; i < ary.length; i++)
{
if (current != ary[i])
{
newARY[i] = ary[i];
current = ary[i];
}
}
for (int i = 0; i < ary.length; i++)
{
if (ary[i] == 0)
{
if (ary[i + 1] != 0)
{
swapper = ary[i + 1];
ary[i] = swapper;
ary[i + 1] = 0;
}
}
}
ary = newARY;
for (int i = 0; i < newARY.length; i++)
{
System.out.print(newARY[i] + " ");
}
}
The array im testing it with is,
int[] aryIn2 = {1, 1, 2, 3, 4, 4, 5, 6};
However, when outputting the imploded array, I receive this one.
1 0 2 3 4 0 5 6
Is there something I am missing?
Thanks in advance.
not an answer to your problem, but using (if possible) java streams can shorten your way:
int[] arr = {1,3,3,4,4,5,6,6,7};
// distinct
List<Integer> list = Arrays.stream(arr).distinct().boxed().collect(Collectors.toList());
// pad with zero's
while(list.size() < arr.length) {
list.add(0);
}
// display
System.out.println(list.stream().map(String::valueOf).collect(Collectors.joining(",")));
will output
1,3,4,5,6,7,0,0,0
Two issue with you code that I observed.
1) Your swapper logic is performing swapping on a different array than the one in which you had done modification earlier
2) You need to have this logic in a bubble-sort way, i.e. loop inside a loop
Below is a working modified sample code of your method. I have modified only the second for-loop logic
public void implode(int[] ary) {
int swapper = -1;
int[] newARY = new int[ary.length];
int current = -1;
for (int i = 0; i < ary.length; i++) {
if (current != ary[i]) {
newARY[i] = ary[i];
current = ary[i];
}
}
for (int i = 0; i < newARY.length - 1; i++) {
if (newARY[i] == 0 && newARY[i + 1] != 0) {
for (int j = i; (j + 1) < newARY.length; j++) {
swapper = newARY[j + 1];
newARY[j] = swapper;
newARY[j + 1] = 0;
}
}
}
for (int i = 0; i < newARY.length; i++) {
System.out.print(newARY[i] + " ");
}
}
In this first loop:
for (int i = 0; i < ary.length; i++) {
if (current != ary[i]) {
newARY[i] = ary[i];
current = ary[i];
}
}
You fill newARY with elements in ary with duplicated value turns to 0:
newARY: 1 0 2 3 4 0 5 6
However, in the second loop:
for (int i = 0; i < ary.length; i++)
{
if (ary[i] == 0)
{
if (ary[i + 1] != 0)
{
swapper = ary[i + 1];
ary[i] = swapper;
ary[i + 1] = 0;
}
}
}
You're modifying your original ary array. So the newARY is not updated.
However, your attempt to push 0 to the end of array also fail if there are more than two 0s consecutive. And it is also vulnerable to ArrayOutOfBoundIndexException since you try to read ary[i+1] without restriction on i
One simple and straight forward way to push 0s to the end of the array is to create new array with non-0s elements and fill 0s later:
int[] result = new int[ary.lenght];
int resultIndex = 0;
for (int i = 0; i < newARY.length; i++) {
if (newARY[i] != 0) {
result[resultIndex++] = newAry[i];
}
}
for (int i = resultIndex; i < newARY.length; i++) {
result[i] = 0;
}
// Print result array
Hint: Using above strategy, you can simplify your code. No need to create immediate array newARY. Just loop over the original array, push unique elements to the result array, then fill any slot left with 0s.

A java Program which take input from 1 to 9 and print all odd from left to right then print even from right to left

I want only one loop to archive this output
input={1,2,3,4,5,6,7,8,9} output={1,3,5,7,9,8,6,4,2}
public static void printOddEven(int[] arr) {
int newArray[] = new int[10];
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 != 0) {
newArray[i] = arr[i];
System.out.print(newArray[i] + " ");
}
}
for (int i = arr.length - 1; i > 0; i--) {
if (arr[i] % 2 == 0) {
newArray[i] = arr[i];
System.out.print(newArray[i] + " ");
}
}
}
If you want to use an array:
int [] result = new int[arr.length];
int counterFront = 0;
int counterBack = arr.length - 1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 != 0) {
result[counterFront++] = arr[i];
}
if (arr[i] % 2 == 0) {
result[counterBack--] = arr[i];
}
}
return result;
EDIT: Thanks to a comment, found out it had a ArrayIndexOutOfBounds.
int newArray[] = new int[9];
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 != 0)
newArray[i/2] = arr[i];
else
newArray[8-(i/2)] = arr[i];
}
System.out.println (java.util.Arrays.toString (newArray));
Just use a descendant index from the right
Why do you use Arrays at all? Is it homework? Note that you get an off-by-one-error, because your newArray is too large, when using int[10] for 9 elements, a typical problem with Arrays.
I reckon this is more of a maths problem than a programming problem. It's about knowing there is a simple arithmetic relationship between an incrementing index and a decrementing index.
int[] arr = {1,2,3,4,5,6,7,8,9};
public static void printOddEven(int[] arr) {
int[] odds = new int[5]; // arr.length == 9
int[] even = new int[4];
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 == 0) {
// This is where the magic happens
// It is filling the array from the back
even[even.length - (i / 2) - 1] = arr[i];
} else {
odds[(i / 2)] = arr[i];
}
}
System.out.println(java.util.Arrays.toString(odds));
System.out.println(java.util.Arrays.toString(even));
}
EDIT:
Just for #CoderinoJavarino, here is a version where the output is a single array. The core logic and maths is identical, so take your pick which is easier to understand.
The use of Arrays.toString() is not there as part of the algorithm solution. It is there simply so that you can see the output. I could equally send the output to a file, or to a web socket.
The output is not the printing, the output is the array or arrays. It could equally have been a List, or a special class just for sorting odd/even numbers. Who cares?
In industrial programming (ie, non-academic) this is how code gets divided up: for ease of understanding, not cleverness. And in the business world there is no concept of "cheating": Nobody worries about the internals of, say, a JSP, rendering your array to a browser.
int[] arr = {1,2,3,4,5,6,7,8,9};
public static int[] SORTOddEven(int[] arr) {
int[] output = new int[arr.length]; // arr.length == 9
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 == 0) {
// This is where the magic happens
// It is filling the array from the back
output[output.length - (i / 2) - 1] = arr[i];
} else {
output[(i / 2)] = arr[i];
}
}
return output;
}
System.out.println(java.util.Arrays.toString(SORTOddEven(arr)));
public static void printOddEven(int[] arr) {
int newArray[] = new int[9];
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 != 0)
newArray[i/2] = arr[i];
else
newArray[arr.length - i/2 - 1] = arr[i];
}
System.out.println(java.util.Arrays.toString(newArray));
}
Live on Ideone.
This only works for 123456789 to print 135798642:
public class Sample {
public static void main(String[] args) throws Exception {
int j=0;
int p=2;
int newArray[]= {1,2,3,4,5,6,7,8,9};
for(int i=0;i<=newArray.length-1;i++)
{
if(i<=4)
{
System.out.print(newArray[i]+j);
j++;
}
else
{
System.err.print(newArray[i]+p);
p=p-3;
}
}
}
}

Inplace quick sort

Write a java program to sort a list of integers using ‘in place’ Quicksort algorithm.
Generate the list randomly every time using the java.util.Random class.
Allow the user to choose the size of the array. The program should display the result of sorting the array of that size using different pivot choices. In particular, try these 4 choices –
 First element as pivot
 Randomly choosing the pivot element
 Choosing the median of 3 randomly chosen elements as the pivot
 Median of first center and last element (book technique).
PLEASE dont give me the implementation because I would like to try on my own. I want to know what is inplace quick sort? How is it different from the regular quiksort. Is it regular quicksort. I am really confused. I would like someone to provide the pusedocode or explanation in plain english will help too.
Inplace sorting - it's when you operate on the original array, given to you from outside, as opposed to creating some new arrays and using them in any way. Inplace sorting takes O(1) space, as opposed to O(n)+ when using additional data structres
Example of inplace sort:
public static void simpleBubbleSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 1; j < arr.length; j++) {
if (arr[j - 1] > arr[j]) {
swap(arr, j - 1, j);
}
}
}
}
As opposed to Merge sort that creates arrays along the way, and by the end combines them and returns NOT the original (given to us) array, but an array containing the result.
public static int[] mergeSort(int[] arr) {
if (arr.length < 2) return arr;
int mid = arr.length / 2;
int[] left = new int[mid];
int[] right = new int[mid + arr.length % 2];
int j = 0;
for (int i = 0; i < arr.length; i++) {
if (i < mid) {
left[i] = arr[i];
} else {
right[j++] = arr[i];
}
}
// keeps going until there's 1 element in each array[]
return mergeReturn(mergeSort(left), mergeSort(right));
}
private static int[] mergeReturn(int[] leftArr, int[] rightArr) {
int leftPointer = 0, rightPointer = 0, combinedSize = leftArr.length + rightArr.length;
int[] merged = new int[combinedSize];
for (int i = 0; i < combinedSize; i++) {
if (leftPointer < leftArr.length && rightPointer < rightArr.length) {
if (leftArr[leftPointer] < rightArr[rightPointer]) {
merged[i] = leftArr[leftPointer++];
} else {
merged[i] = rightArr[rightPointer++];
}
} else if (leftPointer < leftArr.length) { // adding the last element
merged[i] = leftArr[leftPointer++];
} else {
merged[i] = rightArr[rightPointer++];
}
}
return merged;
}

Issue with Java threads, using Runnable or Thread

I'm trying to implement multi-threading using merge sort. I have it making new threads at the point where it cuts an array in half.
The array is sorted depending on the:
[size of the array] vs [how many times I create new threads]
For instance: the array will be sorted if I let it create merely two threads on an array of size 70, but if I let it create 6, it will come back unsorted. One thing I thought it might be is that the threads weren't sync'd, but I used threadName.join()
here is some code: merge.java
import java.util.Random;
public class merge implements Runnable {
int[] list;
int length;
int countdown;
public merge(int size, int[] newList, int numberOfThreadReps, int firstMerge) {
length = size;
countdown = numberOfThreadReps;
list = newList;
if (firstMerge == 1)
threadMerge(0, length - 1);
}
public void run() {
threadMerge(0, length - 1);
}
public void printList(int[] list, int size) {
for (int i = 0; i < size; i++) {
System.out.println(list[i]);
}
}
public void regMerge(int low, int high) {
if (low < high) {
int middle = (low + high) / 2;
regMerge(low, middle);
regMerge(middle + 1, high);
mergeJoin(low, middle, high);
}
}
public void mergeJoin(int low, int middle, int high) {
int[] helper = new int[length];
for (int i = low; i <= high; i++) {
helper[i] = list[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) {
if (helper[i] <= helper[j]) {
list[k] = helper[i];
i++;
} else {
list[k] = helper[j];
j++;
}
k++;
}
while (i <= middle) {
list[k] = helper[i];
k++;
i++;
}
helper = null;
}
public void threadMerge(int low, int high) {
if (countdown > 0) {
if (low < high) {
countdown--;
int middle = (low + high) / 2;
int[] first = new int[length / 2];
int[] last = new int[length / 2 + ((length % 2 == 1) ? 1 : 0)];
for (int i = 0; i < length / 2; i++)
first[i] = list[i];
for (int i = 0; i < length / 2 + ((length % 2 == 1) ? 1 : 0); i++)
last[i] = list[i + length / 2];
merge thread1 = new merge(length / 2, first, countdown, 0);// 0
// is
// so
// that
// it
// doesn't
// call
// threadMerge
// twice
merge thread2 = new merge(length / 2
+ ((length % 2 == 1) ? 1 : 0), last, countdown, 0);
Thread merge1 = new Thread(thread1);
Thread merge2 = new Thread(thread2);
merge1.start();
merge2.start();
try {
merge1.join();
merge2.join();
} catch (InterruptedException ex) {
System.out.println("ERROR");
}
for (int i = 0; i < length / 2; i++)
list[i] = thread1.list[i];
for (int i = 0; i < length / 2 + ((length % 2 == 1) ? 1 : 0); i++)
list[i + length / 2] = thread2.list[i];
mergeJoin(low, middle, high);
} else {
System.out.println("elsd)");
}
} else {
regMerge(low, high);
}
}
}
proj4.java
import java.util.Random;
public class proj4 {
public static void main(String[] args) {
int size = 70000;
int threadRepeat = 6;
int[] list = new int[size];
list = fillList(list, size);
list = perm(list, size);
merge mergy = new merge(size, list, threadRepeat, 1);
// mergy.printList(mergy.list,mergy.length);
for (int i = 0; i < mergy.length; i++) {
if (mergy.list[i] != i) {
System.out.println("error)");
}
}
}
public static int[] fillList(int[] list, int size) {
for (int i = 0; i < size; i++)
list[i] = i;
return list;
}
public static int[] perm(int[] list, int size) {
Random generator = new Random();
int rand = generator.nextInt(size);
int temp;
for (int i = 0; i < size; i++) {
rand = generator.nextInt(size);
temp = list[i];
list[i] = list[rand];
list[rand] = temp;
}
return list;
}
}
so TL;DR my array isn't getting sorted by a multithreaded merge sort based on the size of the array and the number of times I split the array by using threads...why is that?
Wow. This was an interesting exercise in masochism. I'm sure you've moved on but I thought for posterity...
The bug in the code is in mergeJoin with the middle argument. This is fine for regMerge but in threadMerge the middle passed in is (low + high) / 2 instead of (length / 2) - 1. Since in threadMerge low is always 0 and high is length - 1 and the first array has (length / 2) size. This means that for lists with an odd number of entries, it will often fail depending on randomization.
There are also a number of style issues which makes this program significantly more complicated and error prone:
The code passes around a size of the arrays when Java has a convenient list.length call which would be more straightforward and safer.
The code duplicates calculations (see length/2) in a number of places.
The code should be able to sort inside the array without creating sub-arrays.
Classes should start with an uppercase letter (Merge instead of merge)
firstMerge should be a boolean
The code names the Thread variable merge1 and the merge variable thread1. Gulp.
The merge constructor calling threadMerge(0,length -1) is strange. I would just put that call after the new call back in proj4. Then firstMerge can be removed.
I would consider switching to having high be one past the maximum value instead of the maximum. We tend to think like for (int i = 0; i < 10; i++) more than i <= 9. Then the code can have j go from low to < middle and k from middle to < high. Better symmetry.
Best of luck.

Categories