I am trying to implement a B-tree and stuck on the deletion method. When the number of key-value pairs in a node is less than half of a predefined number M, i.e., M / 2, then it needs to combine the consecutive nodes. I am encountering an IndexOutOfBound error, which happens when I needs to delete an element in the first children of the node. Here is the deletion method:
public Value delete(Key key){
return (Value) delete(root, key, HT).value;
}
private Entry delete(Node h, Key key, int ht){
Entry[] children = h.children;
int j = 0;
if(ht == 0){
for(; j < h.m; j++){
if(children[j].key.equals(key)){
break;
}
}
}else {
for(;j < h.m; j++){
if(j + 1 == h.m || key.compareTo((Key) children[j + 1].key) < 0){
Entry deleted = delete(children[j].next, key, ht - 1);
if(children[j].next.m < M / 2){
children[j].next = combine(children[j - 1].next, children[j].next);
if(children[j].next.m == 0)
break;
}
return deleted;
}
}
}
Entry toReturn = children[j];
for(int i = j; i < h.m; i++){
children[i] = children[i + 1];
}
h.m--;
N--;
//if(h.m == 0)
//h = null;
return toReturn;
}
private Node combine(Node a, Node b){
int size = a.m;
for (int i = size; i < size + b.m; i++){
a.children[i] = b.children[i - b.m];
a.m++;
}
if(a.m < M)
b.m = 0;
else
b = split(a);
return b;
}
Here is the whole class, the insertion and searching method can be compiled perfectly fine.
public class BTree <Key extends Comparable<Key>, Value>{
//maximum children per B-tree
private static int M;
private Node root;
//height of the B-tree
private int HT;
//number of key-value pairs in the B-tree
private int N;
/***************************************************************
* private class for the node
***************************************************************/
/**
* tree node class
* Entry list is used for all key - value pairs stored in the node
* m is the index of the pair with the largest key
* since its 0 index, the node contains m + 1 key - value pairs
* #author shirleyyoung
*
*/
private static class Node{
private int m;//current number of key-value pairs, as well as the index where next key-value pair will be added
private Entry[] children = new Entry[M];//the array for the key value pair, different from the children of a tree
private Node(int k){
m = k;
}
}
/**
* The structure to store the key-value pairs
* #author shirleyyoung
*
*/
private static class Entry implements Comparable<Entry>{
private Comparable key;
private Object value;
private Node next;
public Entry(Comparable key, Object value, Node next){
this.key = key;
this.value = value;
this.next = next;
}
public int compareTo(Entry e) {
return key.compareTo(e.key);
}
}
/*******************************************************
* constructor
* M is the maximum key-value pairs a node can store,
* it should be an even value for the sake of split
* #param M
********************************************************/
public BTree(int M){
if(M % 2 != 0)
throw new IllegalArgumentException("Maximum children must be an even number!");
this.M = M;
HT = 0;
N = 0;
root = new Node(0);
}
/******************************************************
* search for an object
*******************************************************/
public Value get(Key key){
return (Value) search(root, key, HT).value;
}
//ht:current height
private Entry search(Node x, Key key, int ht){
Entry[] children = x.children;
//root
if(ht == 0){
for(int j = 0; j < x.m; j++){
if(key.equals(children[j].key))
return children[j];
}
} else{//internal nodes
for(int j = 0; j < x.m; j++){
if(j == x.m - 1|| key.compareTo((Key) children[j + 1].key) < 0)
return search(children[j].next, key, ht - 1);
}
}
return null;
}
/***************************************************
* Insertion
***************************************************/
public void put(Key key, Object value){
Entry tmp = search(root, key, HT);
if(tmp != null){
tmp.value = value;
return;
}
Node u = insert(root, key, value, HT);
N++;
if(u == null) return;
//if the previous node is split, initialize a new node as the root
Node t = new Node(2);//2 children
t.children[0] = new Entry(root.children[0].key, null, root);
t.children[1] = new Entry(u.children[0].key, null, u);
root = t;
HT++;
}
private Node insert(Node h, Key key, Object value, int ht){
int j;
//the key-value pair to be added
Entry toAdd = new Entry(key, value, null);
if(ht == 0){
//find the correct place to insert the value
for(j = 0; j < h.m; j++){
if(key.compareTo((Key) h.children[j].key) < 0)
break;
}
}else {
for(j = 0; j < h.m; j++){
if((j + 1 == h.m) || key.compareTo((Key) h.children[j + 1].key) < 0){
Node u = insert(h.children[j++].next, key, value, ht - 1);
if(u == null) return null;
toAdd.key = u.children[0].key;
toAdd.next = u;
break;
}
}
}
//shift the larger nodes right
for(int i = h.m; i > j; i--) h.children[i] = h.children[i - 1];
h.children[j] = toAdd;
h.m++;
if(h.m < M) return null;
else return split(h);
}
private Node split(Node h){
Node t = new Node(M / 2);
h.m = M / 2;
for(int j = 0; j < M / 2; j++){
t.children[j] = h.children[M / 2 + j];
}
return t;
}
public Value delete(Key key){
return (Value) delete(root, key, HT).value;
}
private Entry delete(Node h, Key key, int ht){
Entry[] children = h.children;
int j = 0;
if(ht == 0){
for(; j < h.m; j++){
if(children[j].key.equals(key)){
break;
}
}
}else {
for(;j < h.m; j++){
if(j + 1 == h.m || key.compareTo((Key) children[j + 1].key) < 0){
Entry deleted = delete(children[j].next, key, ht - 1);
if(children[j].next.m < M / 2){
children[j].next = combine(children[j - 1].next, children[j].next);
if(children[j].next.m == 0)
break;
}
return deleted;
}
}
}
Entry toReturn = children[j];
for(int i = j; i < h.m; i++){
children[i] = children[i + 1];
}
h.m--;
N--;
//if(h.m == 0)
//h = null;
return toReturn;
}
private Node combine(Node a, Node b){
int size = a.m;
for (int i = size; i < size + b.m; i++){
a.children[i] = b.children[i - b.m];
a.m++;
}
if(a.m < M)
b.m = 0;
else
b = split(a);
return b;
}
public String toString(){
return toString(root, HT, "") + "\n";
}
private String toString(Node h, int ht, String indent){
String s = "";
Entry[] children = h.children;
if(ht == 0){
for(int j = 0; j < h.m; j++){
s += indent + children[j].key + "-" + children[j].value + " ";
}
} else{
for(int j = 0; j < h.m; j++){
System.out.println("curr node: " + children[j].key);
s += indent + "\n(" + children[j].key + ")\n";
s += toString(children[j].next, ht - 1, indent + " ");
}
}
return s;
}
public int size(){
return N;
}
public int height(){
return HT;
}
}
Thanks a lot!
Related
We represent the Sudoku as a two-dimensional array. If you want to achieve two columns in one stack are swapped, we need to symmetrically swap the columns of the two-dimensional array. But in the teacher's code, why is the row of the array exchanged? And the result is correct.
private void permutateColumns(int a, int b) {
if(a > 0 && a < 10 && b > 0 && b < 10) {
int[] array = field[a-1];
field[a-1] = field[b-1];
field[b-1] = array;
}
}
all code
package ubung;
import java.util.Random;
//-------------------------------------------------------------- a)
public class Sudoku {
final int n = 3;
final int gridsize = n*n;
int[][] field = new int[gridsize][gridsize];
Random random = new Random();
public Sudoku() {
int[] firstRow = {1,2,3,4,5,6,7,8,9};
//h): int[] firstRow = randomRow();
for (int i = 0; i < gridsize; i++)
for (int j = 0; j < gridsize; j++)
field[i][j] = (i*n + i/n + j) % gridsize + 1;
//h): field[i][j] = firstRow[(i*n + i/n + j) % gridsize];
System.out.println(this);
}
//------------------------------------------------------------- g)
public Sudoku(int permutationCount) {
this();
randomPermutation(permutationCount);
}
//-------------------------------------------------------------- b)
/**Die Methode gibt ein Sudoku-Objekt als einen String zurueck
* #return der String eines Sudoku-Objektes
*/
public String toString() {
String str = line(25);
for(int i = 0; i < 9; i++){
str += "|";
for(int j = 0; j < 9; j++){
str += " " + get(i,j);
if(j == 2 || j == 5 || j == 8)
str += " |";
}
str += "\n";
if(i == 2 || i == 5 || i == 8){
str += line(25);
}
}
return str;
}
/**
* Getter for single entries
*/
private String get(int i, int j) {
if(i < 0 || i > gridsize + 1 || j < 0 || j > gridsize + 1) {
return " ";
}
int m = field[i][j];
if(m == 0)
return " ";
return ""+m;
}
private String line(int n){
String str = "";
for(int i = 0; i < n; i++)
str += "-";
return str+"\n";
}
//-------------------------------------------------------------- c)
/**
* Two rows in one band are swapped. This produces 3!^3 as much solutions. ?????????????????????????
*/
private void permutateRows(int a, int b) {
if(a > 0 && a < 10 && b > 0 && b < 10) {
for(int i = 0; i < gridsize; i++) {
int temp = field[i][a-1];
field[i][a-1] = field[i][b-1];
field[i][b-1] = temp;
}
}
}
/**
* Two columns in one stack are swapped. This produces 3!^3 as much solutions. ????????????????????
*/
private void permutateColumns(int a, int b) {
if(a > 0 && a < 10 && b > 0 && b < 10) {
int[] array = field[a-1];
field[a-1] = field[b-1];
field[b-1] = array;
}
}
//-------------------------------------------------------------- d)
/**
* Two stacks are swapped. This produces 3! as much solutions.
*/
private void permutateStacks(int a, int b) {
if(b < a) {
permutateStacks(b,a);
return;
}
if(a == 1 && b == 2) {
permutateColumns(1,4);
permutateColumns(2,5);
permutateColumns(3,6);
}
else if(a == 1 && b == 3) {
permutateColumns(1,7);
permutateColumns(2,8);
permutateColumns(3,9);
}
else if(a == 2 && b == 3) {
permutateColumns(4,7);
permutateColumns(5,8);
permutateColumns(6,9);
}
}
/**
* Two bands are swapped. This produces 3! as much solutions.
*/
private void permutateBands(int a, int b) {
if(b < a) {
permutateBands(b,a);
return;
}
if(a == 1 && b == 2) {
permutateRows(1,4);
permutateRows(2,5);
permutateRows(3,6);
}
else if(a == 1 && b == 3) {
permutateRows(1,7);
permutateRows(2,8);
permutateRows(3,9);
}
else if(a == 2 && b == 3) {
permutateRows(4,7);
permutateRows(5,8);
permutateRows(6,9);
}
}
//-------------------------------------------------------------- e)
/**
* Two rows in one band are swapped. This produces 3!^3 as much solutions.
*/
private void permutateRows() {
int block = random.nextInt(3);
int a = random.nextInt(3)+1;
int b = random.nextInt(3)+1;
permutateRows(a+block*3,b+block*3);
}
/**
* Two columns in one stack are swapped. This produces 3!^3 as much solutions.
*/
private void permutateColumns() {
int block = random.nextInt(3);
int a = random.nextInt(3)+1;
int b = random.nextInt(3)+1;
permutateColumns(a+block*3,b+block*3);
}
private void permutateStacks() {
int a = random.nextInt(3)+1;
int b = random.nextInt(3)+1;
permutateStacks(a,b);
}
private void permutateBands() {
int a = random.nextInt(3)+1;
int b = random.nextInt(3)+1;
permutateBands(a,b);
}
//-------------------------------------------------------------- f)
/**
* The matrix is transposed. This produces double as much solutions.
*/
private void transpose() {
for (int i = 0; i < gridsize; i++)
for (int j = 0; j < i; j++) {
int temp = field[j][i];
field[j][i] = field[i][j];
field[i][j] = temp;
}
}
//-------------------------------------------------------------- g)
private void randomPermutation(){
switch(random.nextInt(5)) {
case 0: permutateRows(); break;
case 1: permutateColumns(); break;
case 2: permutateStacks(); break;
case 3: permutateBands(); break;
case 4: transpose();
default:
}
}
private void randomPermutation(int n){
for(int i = 0; i < n; i++)
randomPermutation();
}
//-------------------------------------------------------------- h)
/**
* Returns random row of digits. Used to relabel digits in the initial matrix
* This yields 9! as much solutions.
*/
private int[] randomRow(){
boolean[] used = new boolean[gridsize];
int[] row = new int[gridsize];
for(int i = 0; i < gridsize; i++) {
int candidate = random.nextInt(gridsize);
if(!used[candidate]){
used[candidate] = true;
row[i] = candidate+1;
}
else {
i--;
}
}
return row;
}
//-------------------------------------------------------------- i)
private void hide(int n) {
if(n < 0)
n = 0;
if(n > 81)
n = 81;
for(int k = 0; k < n; k++) {
int i = random.nextInt(9); //在方法调用返回介于0(含)和n(不含)伪随机,均匀分布的int值。
int j = random.nextInt(9);
if(field[i][j] != 0)
field[i][j] = 0;
else
k--;
}
}
/*****************************************/ //gegeben
public static void main(String[] args){
Sudoku s = new Sudoku(100000);
System.out.println(s);
s.hide(50);
System.out.println(s);
}
}
We represent the Sudoku as a two-dimensional array. If you want to achieve two columns in one stack are swapped, we need to symmetrically swap the columns of the two-dimensional array. But in the teacher's code, why is the row of the array exchanged? And the result is correct.
If we notate the indices of the 2D array as field[x][y], the provided solution code uses x as the column index and y as the row index. It is important to note that the provided method is not the only correct solution. It would be just as correct to implement x as the row index and y as the column index, so long as the methods were implemented correctly.
I am experiencing an error. Running this program requires referencing the compiled jar file in a command line to specify the targets that must be found in the input file.
The error that is happening is any target string specified in the command line (that is present in the input file) gets an output of " not found", when it should be outputting " found on line {lineNumber}".
I went through the entirety of the class and frankly, I'm completely lost as to where this error occurs.
Any help is appreciated.
Main Class:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Search {
public static void main(String[] args) throws FileNotFoundException {
Scanner in = null;
int index = 0;
String[] word = null;
int[] lineNumber = null;
// check number of command line arguments is at least 2
if (args.length < 2) {
System.out.println("Usage: Search <input file> <target1> [target2...]");
System.exit(1);
}
// initialize Scanner
in = new Scanner(new File(args[0]));
// matches the end of a file character
in.useDelimiter("\\Z");
// puts entire file into one string
String temp = in.next();
in.close();
// intialize arrays & plug elements in
word = temp.split("\n");
lineNumber = new int[word.length];
populate(lineNumber);
// sort String array
mergeSort(word, lineNumber, 0, word.length - 1);
// if multiple targets exist
if (args.length > 2) {
for (int i = 1; i < args.length; i++) {
index = binarySearch(word, 0, word.length - 1, args[i]);
if (index < 0) {
System.out.println(args[i] + " not found");
} else {
System.out.println(args[i] + " found on line " + lineNumber[index]);
}
}
// if only single target specified in command line
} else {
index = binarySearch(word, 0, word.length - 1, args[1]);
if (index < 0) {
System.out.println(args[1] + " not found");
} else {
System.out.println(args[1] + " found on line " + lineNumber[index]);
}
}
}
// recursively halves arrays then plugs into merge function
public static void mergeSort(String[] word, int[] lineNumber, int p, int r) {
int q;
if (p < r) {
// q is midpoint
q = (p + r) / 2;
// recursive stuff
mergeSort(word, lineNumber, p, q);
mergeSort(word, lineNumber, q + 1, r);
// merge arrays
merge(word, lineNumber, p, q, r);
}
}
// merges sorted String arrays into one large sorted String array
public static void merge(String[] word, int[] lineNumber, int p, int q, int r) {
// element ranges
int n1 = q - p + 1;
int n2 = r - q;
// half String arrays to be merged
String[] L = new String[n1];
String[] R = new String[n2];
// half int arrays to be merged
int[] iL = new int[n1];
int[] iR = new int[n2];
// array indexes (for looping)
int i, j, k;
// plugging specific elements into new array
for (i = 0; i < n1; i++) {
L[i] = word[p + i];
iL[i] = lineNumber[p + i];
}
// plugging specific elements into new array
for (j = 0; j < n2; j++) {
R[j] = word[q + j + 1];
iR[j] = lineNumber[q + j + 1];
}
// reset array indexes
i = 0;
j = 0;
// loop through entirety of elements
for (k = p; k <= r; k++) {
// if both arrays still have unmerged element(s)
if (i < n1 && j < n2) {
// if left array's element precedes right's element
// lexicographically
if (L[i].compareTo(R[j]) < 0) {
word[k] = L[i];
lineNumber[k] = iL[i];
i++;
} else { // if right's element precedes (or the words are equal)
word[k] = R[j];
lineNumber[k] = iR[j];
j++;
}
// if only left array has unmerged element(s)
} else if (i < n1) {
word[k] = L[i];
lineNumber[k] = iL[i];
i++;
// if only right array has unmerged element(s)
} else {
word[k] = R[j];
lineNumber[k] = iR[j];
j++;
}
}
}
// searches sorted String array and returns index of target (or -1 if not
// found)
public static int binarySearch(String[] word, int p, int r, String target) {
int q;
if (p > r) {
return -1;
} else {
q = (p + r) / 2;
if (target == word[q]) {
return q;
} else if (target.compareTo(word[q]) < 0) {
return binarySearch(word, p, q - 1, target);
} else {
return binarySearch(word, q + 1, r, target);
}
}
}
// helper method: plugs numbers (in order) into an int array
public static void populate(int[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = i + 1;
}
}
}
You need to change the below method. String should be compared with equals() method and use trim() method to avoid trailing spaces.
public static int binarySearch(String[] word, int p, int r, String target) {
int q;
if (p > r) {
return -1;
} else {
q = (p + r) / 2;
if (target.trim().equals(word[q].trim())) {
return q;
} else if (target.compareTo(word[q]) < 0) {
return binarySearch(word, p, q - 1, target);
} else {
return binarySearch(word, q + 1, r, target);
}
}
}
I have created a method called LineOfRegression and I want to print out an example line of regression with the slope of 0.18784 and a intercept of -7.964. How would I do this in main? (I've pasted the whole class for reference; The LineOfRegression method is at the bottom)
package com.company;
public class ScatterPlot {
public Point[]points = null;
ScatterPlot(Point p){
points = new Point[1];
points[0] = p;
}
public void addPoint(Point p){
Point[]temp = null;
if(points==null || points.length == 0){
points = new Point[1];
points[0] = p;
}
else{
temp = new Point[points.length+1];
//use a for loop to copy points into temp
for(int i = 0; i < points.length; i++){
temp[i] = points[i];
}
//add the new Point p into the last element
temp[points.length] = p;
//copy over temp
points = temp;
}
}
public boolean removeIndex(int index) {
//Points is null
if(points == null){
return false;
}
if(points.length==0){
return false;
}
//Out of bounds index
if(index >= points.length || index <0){
return false;
}
//{p0 p1 p2 p3 p4 p5} index = 3
//P0 - P2
//Copy elements before remove
Point[] newArray = new Point[points.length-1];
for(int i = 0; i<index;i++){
newArray[i] = points[i];
}
//Copy elements after remove
for(int i = index; i<newArray.length; i++){
newArray[i] = points[i+1];
}
points = newArray;
return true;
}
void printReport(){
System.out.println("Number of points " + points.length);
System.out.println("Line of Regression is " + lineOfRegression().toStr());
}
public Line lineOfRegression(){
double n = points.length;
double sigmaX = 0;
double sigmaY = 0;
double sigmaXY = 0;
double sigmaXSquared = 0;
for(int count = 0; count<= n; count++){
sigmaX = sigmaX + points[count].getXCoordinate();
sigmaY = sigmaY + points[count].getYCoordinate();
sigmaXY = sigmaXY + points[count].getXCoordinate() * points[count].getYCoordinate();
}
double slope = (n * sigmaXY) - (sigmaX * sigmaY) / (n + (sigmaXSquared)) - (sigmaXSquared);
double intercept = (sigmaY - (slope * sigmaX)) / n;
Line regressionLine = new Line(slope,intercept);
return regressionLine;
}
}
I have written a sorted vector which works fully. However my Add method is very long and I feel like there is a lot of redundant code.
I have a binary search function written and I would like to use this in my Add method instead of doing comparisons in the Add function also.
Below is my code:
public class SortedVector
{
private int maxcap = 10, noOfItems = 0, grow = 10;
private String[] data = new String[maxcap];
// Default Constructor
public SortedVector()
{
}
public void SetGrowBy(int growby)
{
grow = growby;
}
public int GetCapacity()
{
return maxcap;
}
public int GetNoOfItems()
{
return noOfItems;
}
public String GetItemByIndex(int index)
{
if (index > noOfItems+1 || index < 0)
{
return null;
}
else
{
String item = data[index];
return item;
}
}
public int FindItem(String search)
{
int low=0;
int high = noOfItems - 1;
return binarySearch(search, low, high);
}
public int binarySearch(String search, int low, int high)
{
if(low>high)
return -1;
int mid = (low + high)/2;
if (data[mid] == search)
return mid;
else
if (data[mid].compareToIgnoreCase(search)<0)
return binarySearch(search, mid+1, high);
else
return binarySearch(search, low, mid-1);
}
public void AddItem(String value)
{
int thirdCounter = 0;
int fourthCounter = 0;
int place3= 0;
int place4 =0;
if(maxcap > noOfItems)
{
if(noOfItems == 0)
{
data[0] = value;
noOfItems++;
}
else
{
int firstCounter = noOfItems;
for (int i=0; i < firstCounter; i++)
{
String[]temp = new String[maxcap];
if(thirdCounter == 0)
{
if (data[i].compareToIgnoreCase(value)>0)
{
for (int j=0; j < noOfItems; j++)
{
temp[j+1] = data[j];
}
data=temp;
data[0] = value;
noOfItems++;
thirdCounter++;
}
else
{
if(data[i].compareToIgnoreCase(value)<0)
{
for (int j=0; j < noOfItems; j++)
{
if (data[j].compareToIgnoreCase(value)>0)
{
if(fourthCounter ==0)
{
temp[j+1] = data[j];
place3 = j;
fourthCounter++;
}
else
{
temp[j+1] = data[j];
}
}
else
{
temp[j]=data[j];
place4 = j;
}
}
if (place3 == 0)
{
if(place4 == 0)
{
data=temp;
data[1] = value;
noOfItems++;
firstCounter++;
}
else
{
data=temp;
data[place4+1] = value;
noOfItems++;
thirdCounter++;
}
}
else
{
data=temp;
data[place3] = value;
noOfItems++;
thirdCounter++;
}
}
}
}
}
}
}
else
{
int firstCounter = 0;
maxcap = grow +maxcap;
String[]temp3 = new String[maxcap];
for (int i=0; i < noOfItems; i++)
{
if(firstCounter == 0)
{
if (data[i].compareToIgnoreCase(value)>0)
{
for (int j=0; j < noOfItems; j++)
{
temp3[j+1] = data[j];
}
data=temp3;
data[0] = value;
noOfItems++;
firstCounter++;
}
else
{
int place1 = 0;
int place2 = 0;
int secondCounter = 0;
if(data[i].compareToIgnoreCase(value)<0)
{
for (int j=0; j < noOfItems; j++)
{
if (data[j].compareToIgnoreCase(value)>0)
{
if(j/2!=0 && secondCounter ==0)
{
temp3[j+1] = data[j];
place1 = j;
secondCounter++;
}
else
{
temp3[j+1] = data[j];
}
}
else
{
temp3[j]=data[j];
place2 = j;
}
}
if (place1 == 0)
{
if(place2 == 0)
{
data=temp3;
data[1] = value;
noOfItems++;
firstCounter++;
}
else
{
data=temp3;
data[place2+1] = value;
noOfItems++;
firstCounter++;
}
}
else
{
data=temp3;
data[place1] = value;
noOfItems++;
firstCounter++;
}
}
}
}
}
}
System.out.println("adding: "+value);
}
public void DeleteItem(int index)
{
if (index < noOfItems && index >= 0)
{
data[index] = null;
if (data[index+1] != null)
{
int j = index;
for(int i = (index+1); i<noOfItems; i++)
{
data[j] = data[i];
j++;
}
}
noOfItems--;
}
System.out.println("deleted: "+index);
}
public String toString()
{
return super.toString();
}
}
Any tips on how I could do that much appreciated.
Kind Regards,
Ben.
Implementing the add, (binaryAdd) is almost identical to how you implemented the binary search. The code will be 99% similar.
Let say you have the following data:
+--------------------------+
|10|20|30|40|50|60|70|80|90|
+--------------------------+
You want to add 35 into it and keep the data in ascending order.
The mid value is 50, and since 35 is < 50, we are interested in 10 to 50:
+--------------+
|10|20|30|40|50|
+--------------+
The mid value is 30, and since 35 is > 30, we are interested in 30 to 50:
+--------+
|30|40|50|
+--------+
The mid value is 40, and since 35 is < 40, we are interested in 30 to 40:
+-----+
|30|40|
+-----+
When you left with 2 elements, choose either left or the right for comparison:
if you choose left, 35 > 30, so 35 should be added after 30.
if you choose right, 35 < 40, so 35 should be before after 40.
The process is similar to binary search, but instead of returning the position of the target value, you return the position to insert the value.
Here it is
DEMO: https://repl.it/Eqak/0
public void AddItem(String value)
{
// Check if cursor at last
if(noOfItems + 1 == maxcap){
// Resize data
maxcap *= 2;
String[] newData = new String[maxcap];
System.arraycopy(data, 0, newData, 0, noOfItems);
data = newData;
}
// find the last element according to value
int idx = 0;
for(; idx<noOfItems; idx++){
if(data[idx].compareToIgnoreCase(value) >= 0) {
break;
}
}
// move elements if required
if(idx < noOfItems){
System.arraycopy(data, idx, data, idx+1, noOfItems-idx);
}
// set element on index
data[idx] = value;
noOfItems++;
System.out.println("adding: "+value);
}
The easiest way is make the binarySearch return the insertion position if the element is not found. Very much like Arrays.binarySearch does:
returns: index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1)
So, if the return of the ret=binarySearch is negative, you only need to take -ret-1 to get the insert position.
You can even take a look to the code, its open source anyway (i.e. not only it runs, but you can use it to learn from it)
(no, I won't copy/paste that piece of code; link-only answer - take it or leave it).
I'm trying to implement a Deque utilizing a circular array that extends when the array gets full. However, I am getting an IndexOutOfBoundsException. I think my issue is with the insertLast method. I've analyzed my code thoroughly and I cannot see what I am doing wrong. Any assistance would be greatly appreciated.
public class CircularExtendedArrayDeque
{
public static final int INIT_CAPACITY = 4; // initial array capacity
protected int capacity; // current capacity of the array
protected int front; // index of the front element
protected int rear; // index of the rear element
protected int[] A; // array deque
public CircularExtendedArrayDeque( ) // constructor method
{
A = new int[ INIT_CAPACITY ];
capacity = INIT_CAPACITY;
front = rear = 0;
}
/**
* Print the content of the deque
*
*/
public void printDeque( )
{
for ( int i = front; i != rear; i = (i+1) % capacity )
System.out.print( A[i] + " " );
System.out.println();
}
/**
* Print the content of the whole array
*
*/
public void printArray( )
{
for ( int i = 0; i < capacity; i++ )
System.out.print( A[i] + " " );
System.out.println();
}
// ***************************************
// DO NOT MODIFY THE CODE ABOVE THIS LINE.
// ADD YOUR CODE BELOW THIS LINE.
//
// ***************************************
/**
* Returns the number of items in this collection.
* #return the number of items in this collection.
*/
public int size()
{
// COMPLETE THIS METHOD
return (capacity - front + rear) % capacity;
}
/**
* Returns true if this collection is empty.
* #return true if this collection is empty.
*/
public boolean isEmpty()
{
// COMPLETE THIS METHOD
return front == rear;
}
/**
* Returns the first element of the deque
*
*/
public int getFirst() throws EmptyDequeException
{
// COMPLETE THIS METHOD
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
return A[front % capacity];
}
/**
* Returns the last element of the deque
*
*/
public int getLast() throws EmptyDequeException
{
// COMPLETE THIS METHOD
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
return A[(front + rear - 1) % capacity];
}
/**
* Inserts e at the beginning (as the first element) of the deque
*
*/
public void insertFirst( int e )
{
// COMPLETE THIS METHOD
rear++;
if(size() == capacity - 1){
capacity *= 2;
}
int[] B = new int[capacity];
for(int i = 0; i < size(); i++){
B[i] = A[i];
}
A = B;
for(int i = size(); i >= front; i--){
A[i+1] = A[i];
}
A[front] = e;
front = front % capacity;
System.out.println("Front: " + front + " & Rear:" + rear);
}
/**
* Inserts e at the end (as the last element) of the deque
*
*/
public void insertLast( int e )
{
// COMPLETE THIS METHOD
if(size() == capacity - 1){
capacity *= 2;
int[] B = new int[capacity];
for ( int i = front; i != rear; i = (i+1) % capacity )
B[i] = A[i];
/*
for(int i = 0; i < size(); i++){
B[i] = A[i];
}
*/
A = B;
A[rear++] = e;
}
else{
//System.out.println("Array Size = " + A.length);
A[rear++] = e;
}
System.out.println("Front: " + front + " & Rear:" + rear);
System.out.println("msg...size=" + size());
}
/**
* Removes and returns the first element of the deque
*
*/
public int removeFirst( ) throws EmptyDequeException
{
// COMPLETE THIS METHOD
int result = A[front];
A[front] = 0;
front = (front+1)%capacity;
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
else if(capacity >= 4){
if(size() < capacity/2){
//System.out.println("msg...size = " + size());
capacity /= 2;
int[] B = new int[capacity];
int counter=0;
for(int i = front; i < front+size(); i++){
B[counter] = A[i%(capacity*2)];
counter++;
}
A = B;
front = 0;
rear = size()-1;
}
}
return result;
}
/**
* Removes and returns the last element of the deque
*
*/
public int removeLast( ) throws EmptyDequeException
{
// COMPLETE THIS METHOD
if(isEmpty()){
throw new EmptyDequeException("Deque is empty.");
}
else if(capacity >= 4){
if(size() < capacity/2){
System.out.println("Capacity shrinking...");
int[] B = new int[capacity/2];
for(int i = 0; i < capacity/2; i++){
B[i] = A[i];
}
A = B;
}
}
int temp = A[rear - 1];
A[rear] = 0;
rear = (rear - 1) % capacity;
return temp;
}
} // end class
Here's the main class:
public class CircularExtendedArrayMain {
public static void main(String[] args) {
CircularExtendedArrayDeque q = new CircularExtendedArrayDeque();
q.insertFirst(112);
q.insertFirst(105);
q.printDeque();
System.out.println("last element is = " + q.getLast());
System.out.println("first element is = " + q.getFirst());
q.insertLast(5501);
q.printDeque();
q.insertLast(778);
q.insertLast(37);
q.printDeque();
System.out.println("first element is = " + q.getFirst());
System.out.println("last element is = " + q.getLast());
System.out.println("remove last = " + q.removeLast());
q.printDeque();
System.out.println("remove last = " + q.removeLast());
System.out.println("remove first = " + q.removeFirst());
q.printDeque();
System.out.println("remove first = " + q.removeFirst());
System.out.println("remove first = " + q.removeFirst());
// q is now empty.
int i, k;
for( i = 1; i <= 60; i ++ )
q.insertLast(i*i);
q.printDeque(); // 60 elements in q
for( i = 1; i <= 58; i++ )
k = q.removeFirst();
q.printDeque(); // two elements are left
}
}
Here's my output:
Front: 0 & Rear:1
Front: 0 & Rear:2
105 112
last element is = 112
first element is = 105
Front: 0 & Rear:3
msg...size=3
105 112 5501
Front: 0 & Rear:4
msg...size=4
Front: 0 & Rear:5
msg...size=5
105 112 5501 778 37
first element is = 105
last element is = 37
remove last = 37
105 112 5501 778
remove last = 778
remove first = 105
112 5501
remove first = 112
remove first = 5501
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at CircularExtendedArrayDeque.insertLast(CircularExtendedArrayDeque.java:161)
at CircularExtendedArrayMain.main(CircularExtendedArrayMain.java:34)
public void insertLast(int e) {
if(size() == capacity - 1) {
capacity= capacity*2;
}
int[] B = new int[capacity];
for(int i = 0; i < size(); i++) {
B[i] = A[i];
}
A = B;
A[rear] = e;
rear = (rear + 1) % capacity;
}
This is my insertLast(). Guess this works. Good luck with cse2011.. !!