Okay, this is probably going to come across as a really easy question, but honestly I'm new to coding and I've run up against a brick wall here. I need to insert a value into an array, shift the data to the right, and update the size of the array. The professor provided comments for us to structure our code around, and I've got most of it, but this last part is killing me. Can anyone help? Here's the code (the relevant portion is under //insert value and shift data...etc):
public class List {
// Declare variables
private int size = 0;
private int maxSize = 100;
private int[] data;
Scanner keyboard = new Scanner(System.in);
// constructors
public List() {
data = new int[maxSize];
}
public List(int maxSize) {
this.maxSize = maxSize;
data = new int[maxSize];
}
// methods
// Adds a value into the array and updates the size
public boolean add(int value) {
if (size == maxSize) {
System.out.println("Cannot add value since the list is full");
return false;
}
data[size] = value;
size++;
return true;
}
// add multiple values to the list obtained from the keyboard
public void addValues() {
// declare local variables
int count = 0;
System.out.println("Enter multiple integers separated by spaces");
String line = keyboard.nextLine();
Scanner scanLine = new Scanner(line);
try {
while (scanLine.hasNext()) {
data[size] = scanLine.nextInt();
count++;
size++;
}
} catch (ArrayIndexOutOfBoundsException aiobe) {
System.out.println("Only " + count + " values could be added before the list is full");
return;
} catch (InputMismatchException ime) {
System.out.println("Only " + count + " values could be added due to invalid input");
return;
}
}
// This will print all the elements in the list
public void print() {
System.out.println();
for (int i = 0; i < size; i++) {
System.out.print(data[i] + " ");
}
System.out.println();
}
// This methods returns the index of the key value if found in the list
// and returns -1 if the key value is not in the list
public int find(int key) {
for (int i = 0; i < size; i++) {
if (data[i] == key) {
return i;
}
}
return -1;
}
// This methods deletes the given value if exists and updates the size.
public boolean delete(int value) {
int index = find(value);
if (index == -1) {
System.out.println("The specified value is not in the list");
return false;
}
for (int i = index; i < size - 1; i++) {
data[i] = data[i + 1];
}
size--;
return true;
}
// This methods inserts the value at the given index in the list
public boolean insertAt(int index, int value) {
// validate index value and insertability
if (index < 0 || index > size || size == maxSize) {
System.out.println("Invalid index or list is already full");
return false;
}
// insert value and shift data to the right and update the size
return true;
}
// This method removes the value at given index and shifts the data as needed
public boolean removeAt(int index) {
if (index >= 0 && index < size) {
for (int i=index+1; i<size; i++)
data[i-1] = data[i];
size--;
return true;
}
return false;
}
// This method sorts the values in the list using selection sort
public void sort() {
int temp;
for (int j=size; j>1; j--) {
int maxIndex = 0;
for (int i=1; i<j; i++)
if (data[maxIndex] < data[i])
maxIndex = i;
temp = data[j-1];
data[j-1] = data[maxIndex];
data[maxIndex] = temp;
}
}
}
I apologize if the code is structured really horribly as well, by the way, I was unsure how to format it on this site so it looked right.
// insert value and shift data to the right and update the size
// I think the size is globally declared right?
size++;
for(int i=size - 1; i < 0; i--) {
data[i] = data[i - 1];
}
data[index] = value;
If you have a max size there will also be a check for size <= maxSize. Hope it helps
Think below answer should help. As there is already a size check, no need to check it again
public boolean insertAt(int index, int value) {
// validate index value and insertability
if (index < 0 || index > 5) {
System.out.println("Invalid index or list is already full");
return false;
}
// insert value and shift data to the right and update the size
for(int i=index;i<size;i++) {
data[++i] = data[i];
}
data[index] = value;
return true;
}
public boolean insertAt(int index, int value) {
// validate index value and insertability
if (index < 0 || index > size || size == maxSize) {
System.out.println("Invalid index or list is already full");
return false;
}
// insert value and shift data to the right and update the size
for (int i=size - 1; i > index; i--)
data[i+1] = data[i];
data[index] = value
size++;
return true;
}
Related
I wrote this function to insert an element into a sorted array such that array would still be sorted after adding the element.
But something is wrong. I know that my code has a lot of edge cases and probably I'm over complicating the algorithm but I really want to fix it.
My Code :
private static <E> void insert(E e, E[] arr, int count, Comparator<E> comp) {
if (count == 0) arr[0] = e;
for (int i = 0; i < count; i++) {
if (comp.compare(arr[i], e) >= 0) {
// we found an element that is >= to e
// we want to add new element at index i, currently arr[i] is occupied
// by larger element, so we need to adjust
if (i != 0) {
i--;
} else {
// do nothing
}
} else if (i + 1 == count) {
// this is the last iteration of the loop so we want to add element at i + 1
i++;
} else {
// keep looping to find an element
continue;
}
// we need to move elements to the right to make space
for (int j = count; j > i; j--) {
arr[j] = arr[j - 1];
}
arr[i] = e;
break;
}
}
My repo
I fixed the code, I should have not decremented i
private <E> void insert(E e, E[] arr, int count, Comparator<E> comp) {
if (count == 0) {
arr[0] = e;
return;
}
for (int i = 0; i < count; i++) {
if (comp.compare(arr[i], e) >= 0) {
// we found an element that is >= to e
// we want to add new element at index i, currently arr[i] is occupied
// by larger element, so we need to adjust
} else if (i + 1 == count) {
// this is the last iteration of the loop so we want to add element at i + 1
i++;
} else {
// keep looping to find an element
continue;
}
// we need to move elements to the right to make space
for (int j = count; j > i; j--) {
arr[j] = arr[j - 1];
}
arr[i] = e;
break;
}
}
Sorry for the wordy title but it explains my question pretty well.
I am working on an assignment in Java where I need to create my own Hash Table.
The specifications are such that I must use an Array, as well as open-addressing for collision handling (with both double hashing and quadratic hashing implementations).
My implementation works quite well, and using over 200,000 randomly generated Strings I end up with only ~1400 Collisions with both types of collision handling mentioned about (keeping my load factor at 0.6 and increasing my Array by 2.1 when it goes over).
Here is where I'm stumped, however... My assignment calls for 2 specifications that I cannot figure out.
1) Have an option which, when removing a value form the table, instead of using "AVAILABLE" (replacing the index in the array with a junk value that indicates it is empty), I must find another value that previously hashed to this index and resulted in a collision. For example, if value A hashed to index 2 and value B also hashed to index 2 (and was later re-hashed to index 5 using my collision handling hash function), then removing value A will actually replace it with Value B.
2) Keep track of the maximum number of collisions in a single array index. I currently keep track of all the collisions, but there's no way for me to keep track of the collisions at an individual cell.
I was able to solve this problem using Separate Chaining by having each Array Index hold a linked list of all values that have hashed to this index, so that only the first one is retrieved when I call my get(value) method, but upon removal I can easily replace it with the next value that hashed to this index. It's also an easy way to get the max number of collisions per index.
But we were specifically told not to use separate chaining... I'm actually wondering if this is even possible without completely ruining the complexity of the hash table.
Any advice would be appreciated.
edit:
Here are some examples to give you an idea of my class structure:
public class daveHash {
//Attributes
public String[] dTable;
private double loadFactor, rehashFactor;
private int size = 0;
private String emptyMarkerScheme;
private String collisionHandlingType;
private int collisionsTotal = 0;
private int collisionsCurrent = 0;
//Constructors
public daveHash()
{
dTable = new String[17];
rehashFactor = 2.1;
loadFactor = 0.6;
emptyMarkerScheme = "A";
collisionHandlingType = "D";
}
public daveHash(int size)
{
dTable = new String[size];
rehashFactor = 2.1;
loadFactor = 0.6;
emptyMarkerScheme = "A";
collisionHandlingType = "D";
}
My hashing functions:
public long getHashCode(String s, int index)
{
if (index > s.length() - 1)
return 0;
if (index == s.length()-1)
return (long)s.charAt(index);
if (s.length() >= 20)
return ((long)s.charAt(index) + 37 * getHashCode(s, index+3));
return ((long)s.charAt(index) + 37 * getHashCode(s, index+1));
}
public int compressHashCode(long hash, int arraySize)
{
int b = nextPrime(arraySize);
int index = ((int)((7*hash) % b) % arraySize);
if (index < 0)
return index*-1;
else
return index;
}
Collision handling:
private int collisionDoubleHash(int index, long hashCode, String value, String[] table)
{
int newIndex = 0;
int q = previousPrime(table.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < table.length; i++)
{
newIndex = (index + i*secondFunction) % table.length;
//System.out.println(newIndex);
if (isAvailable(newIndex, table))
{
table[newIndex] = value;
return newIndex;
}
}
return -1;
}
private int collisionQuadraticHash(int index, long hashCode, String value, String[] table)
{
int newIndex = 0;
for (int i = 0; i < table.length; i ++)
{
newIndex = (index + i*i) % table.length;
if (isAvailable(newIndex, table))
{
table[newIndex] = value;
return newIndex;
}
}
return -1;
}
public int collisionHandling(int index, long hashCode, String value, String[] table)
{
collisionsTotal++;
collisionsCurrent++;
if (this.collisionHandlingType.equals("D"))
return collisionDoubleHash(index, hashCode, value, table);
else if (this.collisionHandlingType.equals("Q"))
return collisionQuadraticHash(index, hashCode, value, table);
else
return -1;
}
Get, Put and Remove:
private int getIndex(String k)
{
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (dTable[index] != null && dTable[index].equals(k))
return index;
else
{
if (this.collisionHandlingType.equals("D"))
{
int newIndex = 0;
int q = previousPrime(dTable.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < dTable.length; i++)
{
newIndex = (index + i*secondFunction) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return newIndex;
}
}
}
else if (this.collisionHandlingType.equals("Q"))
{
int newIndex = 0;
for (int i = 0; i < dTable.length; i ++)
{
newIndex = (index + i*i) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return newIndex;
}
}
}
return -1;
}
}
public String get(String k)
{
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (dTable[index] != null && dTable[index].equals(k))
return dTable[index];
else
{
if (this.collisionHandlingType.equals("D"))
{
int newIndex = 0;
int q = previousPrime(dTable.length);
int secondFunction = (q - (int)hashCode) % q;
if (secondFunction < 0)
secondFunction = secondFunction*-1;
for (int i = 0; i < dTable.length; i++)
{
newIndex = (index + i*secondFunction) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return dTable[newIndex];
}
}
}
else if (this.collisionHandlingType.equals("Q"))
{
int newIndex = 0;
for (int i = 0; i < dTable.length; i ++)
{
newIndex = (index + i*i) % dTable.length;
if (dTable[index] != null && dTable[newIndex].equals(k))
{
return dTable[newIndex];
}
}
}
return null;
}
}
public void put(String k, String v)
{
double fullFactor = (double)this.size / (double)dTable.length;
if (fullFactor >= loadFactor)
resizeTable();
long hashCode = getHashCode(k, 0);
int index = compressHashCode(hashCode, dTable.length);
if (isAvailable(index, dTable))
{
dTable[index] = v;
size++;
}
else
{
collisionHandling(index, hashCode, v, dTable);
size++;
}
}
public String remove(String k)
{
int index = getIndex(k);
if (dTable[index] == null || dTable[index].equals("AVAILABLE") || dTable[index].charAt(0) == '-')
return null;
else
{
if (this.emptyMarkerScheme.equals("A"))
{
String val = dTable[index];
dTable[index] = "AVAILABLE";
size--;
return val;
}
else if (this.emptyMarkerScheme.equals("N"))
{
String val = dTable[index];
dTable[index] = "-" + val;
size--;
return val;
}
}
return null;
}
Hopefully this can give you an idea of my approach. This does not include the Separate Chaining implementation I mentioned above. For this, I had the following inner classes:
private class hashList
{
private class hashNode
{
private String element;
private hashNode next;
public hashNode(String element, hashNode n)
{
this.element = element;
this.next = n;
}
}
private hashNode head;
private int length = 0;
public hashList()
{
head = null;
}
public void addToStart(String s)
{
head = new hashNode(s, head);
length++;
}
public int getLength()
{
return length;
}
}
And my methods were modified appropriate to access the element in the head node vs the element in the Array. I took this out, however, since we are not supposed to use Separate Chaining to solve the problem.
Thanks!!
Hello I have got this basically fully working sorted vector , the problem here is however that I can only initialize the array to a fixed size before inserting any values , so for example I can initialize 5 but if I want to insert 6 items it gives me a null pointer exception .
I think I do understand what is happening however I would like anybody to show me a solution how the array size can be increased automatically every time I want to insert something .
( Without having to use any inbuilt java functionalities like ArrayList )
Thank you
package ads2;
public class SortedVector2
{
private int length;
private int maximum;
private int growby;
private int temp;
private int x = 0;
private int high;
private int middle;
private int low;
String[] data;
public SortedVector2()
{
length = 0;
maximum = 5;
data = new String[maximum];
}
public void AddItem(String value)
{
/*if (length == maximum)
{
maximum += 200000;
*/
data[length] = value;
length++;
// SetSorted();
// SetSorted(data);
}
public void SetSorted()
{
for (int j = 0; j < data.length - 1; j++) {
if (data[j].compareTo(data[j + 1]) > -1) {
String temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
for (String s : data) {
System.out.println(s);
}
// private String[] data;
/*
for(int i = data.length-1; i >= 0; i--) {
for(int j = 0; j < i; j++) {
if(data[j].compareTo(data[j + 1]) > -1) {
String temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
} for (String s : data) {
System.out.println(s);
}
*/
}
public void SetGrowBy(int growby)
{
maximum += growby;
}
public int GetCapacity()
{
return maximum;
}
public int GetNoOfItems()
{
return length;
}
public String GetItemByIndex(int index)
{
return data[index];
}
public int FindItem(String search)
{
for (x=0;x<=length; )
{
middle =((low + high)/2);
if (data[middle].compareTo(search)==0)
{
return middle;
}
else if (data[middle].compareTo(search)<0)
{
low = middle;
x++;
return FindItem(search);
}
else
{
high = middle;
x++;
return FindItem(search);
}
}
return -1;
}
public boolean Exists(String search)
{
boolean output;
int y;
y = 0;
while (data[y] != search && (length - 1) > y)
{
++y;
}
if (data[y] == search)
{
output = true;
} else
{
output = false;
}
y = 0;
return output;
}
public void InsertItem(int index, String value)
{
if (length == maximum)
{
maximum += 200000;
}
for(int i = length - 1; i >= index; --i)
{
data[i + 1] = data[i];
}
data[index] = value;
length++;
}
public void DeleteItem(int index)
{
for(int x = index; x < length - 2; ++x)
{
data[x] = data[x + 1];
}
length--;
}
public String toString()
{
String res = "";
for (int i=0; i<length; i++)
res+=data[i] + "; ";
return res;
}
}
You have to do what the implementers of ArrayList did. When you try to add an element when the array is full, you create a larger array, copy the existing elements to it and add the new element.
To increase array size dynamically use Collection framework interface List,
It has implementation ArrayList,Vector and LinkedList use any one in them.
Or, Simply create copyArray(String[]) api which will give you array with increased capacity.
public String[] copyArray(String[] oldArray){
int capacity = oldArray.length * 2;
return Arrays.copyOf(oldArray, capacity);
}
String[] data = copyArray(data) // pass array
I think you've got all the basic variables you need to do what you need to do: just check if the size equals the capacity when you are adding an item and if it does reallocate the array:
if (size == capacity) {
capacity += growby;
data = Arrays.copyOf(data, capacity);
}
That's pretty much all ArrayList does.
You need to re-allocate when increasing the size of the data buffer, for example,
public void InsertItem(int index, String value)
{
String[] data2;
if (length == (maximum-1))
{
maximum += 5; // increment size in lot of 5
data2 = new String[maximum);
for (int ii = 0; ii < length; ii++)
{
data2[ii] = date[ii];
}
data = data2; // re-assign with increased size
}
for(int i = length - 1; i >= index; --i)
{
data[i + 1] = data[i];
}
data[index] = value;
length++;
}
In software engineering there is a saying, "Don't reinvent the wheel" - which emphasizes us on using the existing archetype. Because they are tested and used by for long period of time. So it's better to use ArrayList for regular/professional purpose.
But it if it is for learning purpose then you can chose any one from the previous answers.
maxRec() is meant to calculate the maximum value within an array using a helper
method maximize(). When this code executes, it always seems to return zero, however
it will print out the correct value. When using a debugger, I noticed that
the maxRec() method will get the right return value but wont return it; instead it sets it back to zero and moves up to the else statement.I would be grateful for any suggestions that could help fix this.
public int maxRec(int[] v) {
int maxValue = 0;
int[] tempArray = maximize(v);
boolean executeCode = true;
if (tempArray.length == 1) {
maxValue = tempArray[0];
executeCode = false;
System.out.println(maxValue);
} else if (executeCode == true && tempArray.length != 1) {
maxRec(tempArray);
}
return maxValue;
}
public int[] maximize(int[] v) {
int count = 0;
int secondCount = 0;
for (int i = 0; i < v.length; i++) {
if (v[i] > v[0]) {
count++;
}
}
int[] newArray;
newArray = new int[count];
for (int i = 0; i < v.length; i++) {
if (v[i] > v[0]) {
newArray[secondCount] = v[i];
secondCount++;
}
}
return newArray;
}
Code should be changed like this.
public int maxRec(int[] v)
{
int maxValue=0;
int[] tempArray = maximize(v);
boolean executeCode = true;
if(tempArray.length==1)
{
maxValue=tempArray[0];
executeCode=false;
}
else if(executeCode==true && tempArray.length!=1 && tempArray.length > 0)
{
maxValue = maxRec(tempArray);
}
return maxValue;
}
public int[] maximize(int[] v)
{
int count=0;
int secondCount=0;
for(int i=0;i<v.length;i++)
{
if(v[i]>v[0])
{
count++;
}
}
int[] newArray;
newArray = new int[count];
if(count == 0)
{
newArray = new int[1];
newArray[0] = v[0];
return newArray;
}
for(int i=0;i<v.length;i++)
{
if(v[i]>v[0])
{
newArray[secondCount]=v[i];
secondCount++;
}
}
return newArray;
}
maximize returns an array of all values greater than the first item of the array.
To make a recursive function, one starts with the simplest case, the least work.
The rest one delegates to a clone of oneself, the recursive call.
public int maxRec(int[] v) {
if (v.length == 0) {
throw IllegalArgumentException();
}
int[] greaterThanFirst = maximize(v);
int maxValue = 0;
if (greaterThanFirst.length == 0) {
maxValue = v[0];
} else {
maxValue = maxRec(greaterThanFirst);
}
return maxValue;
}
First a sanity check, v not being empty.
If maximize did not yield a larger number, yield the first value, being the largest.
//-------------------------------------------------------------------
// 1. maxRec --> Computes the maximum item of MyList
//-------------------------------------------------------------------
/**
* The function computes the maximum item of m (-1 if m is empty).
* #param m: The MyList we want to compute its maximum item.
* #return: The maximum item of MyList
*/
public int maxRec(MyList<Integer> m){
int max = 0;
int res = 0;
int e0 = 0;
int e1 = 0;
// Scenarios Identification
int scenario = 0;
// Type 1. MyLyst is empty
if(m.length() == 0) {
scenario = 1;
}else {
scenario = 2;
}
// Scenario Implementation
switch(scenario) {
// If MyLyst is empty
case 1:
res = -1;
break;
// If there is 1 or more elements
case 2:
// Old School
for(int i = 0; i <= m.length()-1; i++)
if(m.getElement(i) > max) {
max = m.getElement(i);
}
// Recursively
//1. Get and store first element of array
e0 = m.getElement(0);
//2. We remove the first element from MyList we just checked
m.removeElement(0);
//3. We recursively solve the smaller problem
e1 = maxRec(m);
//4. Compare and store results
if(e0 > e1) {
res = e0;
}
else {
res = e1;
}
//5. Return removed element back to the array
m.addElement(0, e0);
break;
}
//6.Display the process to see what's going on
System.out.println("My Way: "+ max);
System.out.println("Recursive Way: " + res);
//7. Return result
return res;
}
i am trying to create method named split that divides a list into 2 lists according to a key. If list_1 and list_2 are the resulting lists, list_1 should contain all the items of the original list whose keys are less than or equal to the key passed and list_2 should contain all the items of the original list whose keys are larger than the key passed. I will post my code so far and what other people have suggested
public class UnorderedArrayList extends ArrayListClass {
public UnorderedArrayList() {
super();
}
public UnorderedArrayList(int size) {
super(size);
}
//Bubble Sort
public void bubbleSort() {
for (int pass = 0; pass < length - 1; pass++) {
for (int i = 0; i < length - 1; i++) {
if (list[i] > list[i + 1]) {
int temp = list[i];
list[i] = list[i + 1];
list[i + 1] = temp;
}
}
}
}
//implementation for abstract methods defined in ArrayListClass
//unordered list --> linear search
public int search(int searchItem) {
for(int i = 0; i < length; i++)
if(list[i] == searchItem)
return i;
return -1;
}
public void insertAt(int location, int insertItem) {
if (location < 0 || location >= maxSize)
System.err.println("The position of the item to be inserted is out of range.");
else if (length >= maxSize)
System.err.println("Cannot insert in a full list.");
else {
for (int i = length; i > location; i--)
list[i] = list[i - 1]; //shift right
list[location] = insertItem;
length++;
}
}
public void insertEnd(int insertItem) {
if (length >= maxSize)
System.err.println("Cannot insert in a full list.");
else {
list[length] = insertItem;
length++;
}
}
public void replaceAt(int location, int repItem) {
if (location < 0 || location >= length)
System.err.println("The location of the item to be replaced is out of range.");
else
list[location] = repItem;
}
public void remove(int removeItem) {
int i;
if (length == 0)
System.err.println("Cannot delete from an empty list.");
else {
i = search(removeItem);
if (i != -1)
removeAt(i);
else
System.out.println("Cannot delete! The item to be deleted is not in the list.");
}
}
public void merge(UnorderedArrayList list2,UnorderedArrayList list1){
int num=0;
for(int j=0; j<list1.length;j++){
num= list1.retrieveAt(j);
insertEnd(num);
}
for(int i=0; i<list2.length-1;i++){
num=list2.retrieveAt(i);
insertEnd(num);
}
}
public void split(UnorderedArrayList list2, UnorderedArrayList list1, UnorderedArrayList list, int item){
int listItem = item;
while(!list.isEmpty()){
list.retrieveAt(listItem);
if(listItem>item){
if(!list2.isFull()){
list2.insertAt(listItem);
}
}
}
}
//what i got so far from the internet
/* void UnsortedType::SplitLists(ItemType item, UnsortedType& list1, UnsortedType& list2){
ItemType listItem;
list.ResetList();
while ( !list.IsLastItem()) {
list.GetNextItem(listItem);
if(listItem > item) {
if (!list2.IsFull())
list2.InsertItem(listItem);
}
else {
if ( !list1.IsFull())
list1.InsertItem(listItem);
} }}
*/
You have a lot of code, most unrelated to your requirement. Given the list and the key, I would simply:
create the two result lists
iterate through the original list, copying the element to one of the result lists depending on its value relative to key
return the two result lists
That's all you need.
Had this same problem. You will want to clear the two lists you have already done away with(list1 and list2) so that they are available to receive values. Look at the following code I put together, which worked in my program, as a guide. For the method call in your client, your parameters should be: (list_1, list_2, result, split) . Your new lists will be available to you in the client in accordance with their names there.
public void split(UnorderedArrayList list1, UnorderedArrayList list2, UnorderedArrayList list3, int key) {
int num = 0;
list1.clearList();
list2.clearList();
for(int x = 0; x < list3.length; x++) {
num = list3.retrieveAt(x);
if(num <= key)
list1.insertEnd(num);
else
list2.insertEnd(num);
}
}
Hope this helps.