Java 将对象添加到已排序数组中的正确位置
所以我有这个项目,我正在为我的catalog类编写add方法,这个add方法需要使用插入排序将一个项添加到一个排序数组中的正确位置,除非数组中没有任何内容。在这种情况下,我只想正常添加它。整个项目必须使用数组,我不能使用arraylist或其他任何东西 我在这里遇到的问题是,我的程序目前的方式是,它只向数组中添加一个对象,每次我尝试在运行期间添加一个新对象时,jst都会替换其中已有的项。我知道我的问题在于while循环的主体和初始化位置变量的方式 这是我遇到麻烦的方法Java 将对象添加到已排序数组中的正确位置,java,Java,所以我有这个项目,我正在为我的catalog类编写add方法,这个add方法需要使用插入排序将一个项添加到一个排序数组中的正确位置,除非数组中没有任何内容。在这种情况下,我只想正常添加它。整个项目必须使用数组,我不能使用arraylist或其他任何东西 我在这里遇到的问题是,我的程序目前的方式是,它只向数组中添加一个对象,每次我尝试在运行期间添加一个新对象时,jst都会替换其中已有的项。我知道我的问题在于while循环的主体和初始化位置变量的方式 这是我遇到麻烦的方法 public void a
public void addItem(Item theItem)
{
int position = size;
if(size != 0){
while (position > 0 && theItem.compareTo(items[position - 1]) < 0){
items[position] = items[position - 1];
position--;
}
items[position] = theItem;
}
else{
items[size] = theItem;
size++;
}
代码中最可能出现的问题是这一行:
items[position-1] = items[position];
这将把数组中的项目从当前位置复制到其左侧的位置
插入新项目时,要将项目从左侧复制到当前位置,以便为左侧的新项目腾出空间
换成
items[position] = items[position-1];
在while
块之后,在第一个if
块内部,也缺少size++
当我在下面的测试代码中向addItem
添加第二个调用时,我意识到了这一点
您还可以将单个size++
语句放在if
语句之外
一个完整的,最小的,可复制的例子,我用它来修复它。我使用了
Integer
而不是Item
来避免添加更多的类
public class Main {
private int size = 0;
private Integer[] items = new Integer[20];
public static void main(String... args) {
new Main().execute(); // Moving us into a non-static context
}
public void execute() {
System.arraycopy(new Integer[] {1,2,3,4,6,7,8,9}, 0, items, 0, 8);
size = 8;
// items = [1,2,3,4,6,7,8,9,null,null,...]
addItem(5);
addItem(5); // test adding a second item
// items = [1,2,3,4,5,6,7,8,9,null,null,...]
for (Integer i : items) {
System.out.println(i);
}
}
public void addItem(Integer item) {
int position = size;
if (size != 0) {
while (position > 0 && item.compareTo(items[position - 1]) < 0) {
// items[position-1] = items[position]; // Result [1,2,3,4,5,null,null,...]
items[position] = items[position-1]; // Result [1,2,3,4,5,6,7,8,9,null,null,...]
position--;
}
items[position] = item;
size++; // this line was missing as well
} else {
items[size] = item;
size++;
}
// or a single size++; here, removing the other two
}
}
公共类主{
私有整数大小=0;
私有整数[]项=新整数[20];
公共静态void main(字符串…参数){
new Main().execute();//将我们移动到非静态上下文中
}
public void execute(){
数组复制(新整数[]{1,2,3,4,6,7,8,9},0,items,0,8);
尺寸=8;
//项目=[1,2,3,4,6,7,8,9,空,空,…]
增补(5);
addItem(5);//添加第二项的测试
//项目=[1,2,3,4,5,6,7,8,9,空,空,…]
用于(整数i:项目){
系统输出打印LN(i);
}
}
公共无效附加项(整数项){
int位置=大小;
如果(大小!=0){
而(位置>0&&item.compareTo(项目[位置-1])<0){
//items[position-1]=items[position];//结果[1,2,3,4,5,null,null,…]
items[position]=items[position-1];//结果[1,2,3,4,5,6,7,8,9,null,null,…]
位置--;
}
项目[位置]=项目;
size++;//这一行也丢失了
}否则{
项目[大小]=项目;
大小++;
}
//或者一个尺寸++;这里,去掉另外两个
}
}
制作新阵列的丑陋解决方案
public int[] addItem(int item, int[] items){
int[] tempArr = new int[items.length + 1];
boolean hasAlready = false;
for(int i = 0 ; i < items.length; i++){
if(hasAlready)tempArr[i + 1] = items[i];
else if(item < items[i]){
tempArr[i] = item;
tempArr[i + 1] = items[i];
hasAlready = true;
}else {
tempArr[i] = items[i];
}
}
//items = tempArr; if items is global variable
return tempArr;
}
public int[]附加项(int项,int[]项){
int[]tempArr=新int[items.length+1];
布尔值=false;
对于(int i=0;i
可以使用现有的实用程序功能和System.arraycopy
。你的循环是1关
public void addItem(Item theItem) {
Comparator<Item> comparator = Comparator.comparing(Item::getItemType)
.thenComparingInt(it -> it.itemnum);
int position = Arrays.binarySearch(items, 0, size, theItem, comparator);
// If position >= 0 the item was found (maybe no need to insert?)
if (position < 0) {
position = ~position; // Insert position of not found item
}
System.arraycopy(items, position, items, position + 1, size - position);
items[position] = theItem;
size++;
}
公共作废附加项(项){
Comparator Comparator=Comparator.comparing(Item::getItemType)
.然后比较(it->it.itemnum);
int position=Arrays.binarySearch(items、0、size、item、comparator);
//如果位置>=0,则找到项目(可能不需要插入?)
如果(位置<0){
position=~position;//插入未找到项的位置
}
系统阵列副本(项目,位置,项目,位置+1,大小-位置);
项目[位置]=项目;
大小++;
}
二进制搜索结果在找到时为非负索引,或在未找到时为负~索引。在这里,二进制搜索是在从0到大小(排除)的子阵列上进行的。与Roger Gustavsson相同
public class Main {
private int size = 0;
private Integer[] items = new Integer[20];
public static void main(String... args) {
new Main().execute(); // Moving us into a non-static context
}
public void execute() {
System.arraycopy(new Integer[] {1,2,3,4,6,7,8,9}, 0, items, 0, 8);
size = 8;
// items = [1,2,3,4,6,7,8,9,null,null,...]
addItem(5);
// items = [1,2,3,4,5,6,7,8,9,null,null,...]
for (Integer i : items) {
System.out.println(i);
}
}
public void addItem(Integer item) {
if (size == 0) {
items[size] = item;
size++;
return;
}
int position = size;
while (position > 0 && item.compareTo(items[position - 1]) < 0) {
items[position] = items[position - 1];
position--;
}
items[position] = item;
size++;
}
}
公共类主{
私有整数大小=0;
私有整数[]项=新整数[20];
公共静态void main(字符串…参数){
new Main().execute();//将我们移动到非静态上下文中
}
public void execute(){
数组复制(新整数[]{1,2,3,4,6,7,8,9},0,items,0,8);
尺寸=8;
//项目=[1,2,3,4,6,7,8,9,空,空,…]
增补(5);
//项目=[1,2,3,4,5,6,7,8,9,空,空,…]
用于(整数i:项目){
系统输出打印LN(i);
}
}
公共无效附加项(整数项){
如果(大小==0){
项目[大小]=项目;
大小++;
返回;
}
int位置=大小;
而(位置>0&&item.compareTo(项目[位置-1])<0){
项目[位置]=项目[位置-1];
位置--;
}
项目[位置]=项目;
大小++;
}
}
关于您试图实现的目标,我认为下一个解决方案将是您可以根据具体需求构建自己的解决方案的起点。我对您的主方法做了一些更改,我不知道您的类是否实现了comparable/Comparator
public void addItem(Item theItem) {
int position = position(items, theItem); // position is a method that finds best position for inseriton
if (items[position] == null){ // if items at best position is null then add new element there
items[position] = theItem;
} else{
items[size] = theItem; // if not add element at last position
swapUp(size); // and swap them up to perfect position.
}
size++;
}
找到最佳位置的方法如下所示
private static int position(Item[] items, Item newItem) {
if (isEmpty(items))
return 0;
int pos=0;
int target=items.length-1;
while(pos < target){
int m = pos+(target-pos)/2;
if (items[m] !=null){
if(newItem.getNumber()>items[m].getNumber()){ // comparing depending on item number
pos=m+1;
}else{
target=m;
}
}else{
target = m;
}
}
return pos;
}
正如你所看到的,它们是按顺序排列的。这个问题与你之前的问题有何不同?如果数组已排序,您可以使用二进制搜索。@Glains他昨天已经被建议这样做了。我不能使用二进制搜索,我必须以类似的方式进行搜索,有人告诉我,我的问题在我的loopar数组的主体中
private static int position(Item[] items, Item newItem) {
if (isEmpty(items))
return 0;
int pos=0;
int target=items.length-1;
while(pos < target){
int m = pos+(target-pos)/2;
if (items[m] !=null){
if(newItem.getNumber()>items[m].getNumber()){ // comparing depending on item number
pos=m+1;
}else{
target=m;
}
}else{
target = m;
}
}
return pos;
}
private void swapUp(int lastPosition){
if (lastPosition == -1){
return;
}
Item lastItem = items[lastPosition];
Item p = items[lastPosition-1];
if (lastItem.getNumber() < p.getNumber())
replace(lastPosition, lastPosition-1);
else
lastPosition = 0;
swapUp(lastPosition-1);
}
private void replace(int from, int to){
Item temporary = items[from];
items[from] = items[to];
items[to] = temporary;
}
Music{number=1111, name='White and Nerdy', price=2.5, pro='"Weird Al" Yankovic'}
Music{number=2222, name='Amish Paradise', price=2.22, pro='"Weird Al" Yankovic'}
Music{number=3333, name='The Saga Begins', price=2.0, pro='"Weird Al" Yankovic'}
Movie{number=4444, name='UHF', price=9.99, pro='"Weird Al" Yankovic'}
Movie{number=5555, name='The Dark Crystal', price=8.99, pro='"Jim Henson'}
Movie{number=6666, name='Die Hard', price=13.99, pro='Bruce Willis'}
Movie{number=6969, name='The Adventures of Mr. Winky', price=9.99, pro='Richard Dickinson'}
Book{number=7777, name='When I Grow Up', price=7.98, pro='"Weird Al" Yankovic'}
Book{number=8888, name='The Chronicles of Pern: First Fall', price=5.99, pro='"Anne McCaffrey'}
Book{number=9999, name='Get gud you scrub', price=2.5, pro='Steve "Troll" Rathier'}