如何删除数组中的项目并保持顺序不变?
How to delete an item in the array and keeping the order the same?
我正在从事这个允许我在数组中添加和删除元素的项目。当我删除数组中的元素时,space 中会有一个零,代码应该在删除的值之后移动值以取代它的位置。例如:在数组 {1, 2, 3, 4, 5} 中。我选择删除 3。我的输出应该是 {1, 2, 4, 5}。相反,我的输出是 {1, 2, 5, 4}。有人可以帮我弄清楚为什么会那样做吗?以及如何纠正?
import java.util.Scanner;
import java.util.Arrays;
public class IntBag2 {
private static final int INITIAL_SIZE = 20;
private static int[] bag;
private int capacity;
public IntBag2() {
bag = new int[INITIAL_SIZE];
}
public IntBag2(int capacity) {
bag = new int[capacity];
}
public boolean add(int item) {
if (capacity == bag.length)
return false;
bag[capacity++] = item;
return true;
}
public boolean delete(int item) {
for (int i = 0; i < capacity; i++) {
if (bag[i] == item) {
bag[i] = bag[--capacity];
return true;
}
}
return false;
}
@Override
public String toString() {
String result = "Bag: ";
for (int i = 0; i < capacity; i++)
result += bag[i] + " ";
return result;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
IntBag2 intBag = new IntBag2();
boolean done = false;
while (!done) {
System.out.println("1. Add an Item to the Array");
System.out.println("2. Delete an item in the Array");
System.out.println("3. toString");
switch (input.nextInt()) {
case 1:
System.out.println("Add an Item to the Array");
System.out.println(intBag.add(input.nextInt()));
break;
case 2:
System.out.println("Delete Item of Array");
System.out.println(intBag.delete(input.nextInt()));
break;
case 3:
System.out.println("toString");
System.out.println(intBag.toString());
break;
}
}
input.close();
}
}
使用 bag[i] = bag[--capacity];
行,您基本上是在获取数组中的最后一项并将其放置在已删除项的位置。
鉴于您使用的是 int[]
(而不是 Integer[]
),我们无法将数组的索引分配为 null
。我们能做的最好的就是分配它 -1
或创建一个新数组。
我决定从头开始创建一个新数组。以下内容可以解决问题。
public class IntBag2 {
private static final int INITIAL_SIZE = 20;
private static int[] bag;
private int capacity;
public IntBag2() {
bag = new int[INITIAL_SIZE];
}
public IntBag2(int capacity) {
bag = new int[capacity];
}
public boolean add(int item) {
if (capacity == bag.length)
return false;
bag[capacity++] = item;
return true;
}
public boolean delete(int item) {
int[] newBag = new int[capacity];
int newCapacity = capacity;
boolean deleted = false;
for (int i = 0, j = 0; i < capacity; i++) {
if (bag[i] == item && !deleted) {
deleted = true;
newCapacity = capacity - 1;
} else {
newBag[j++] = bag[i];
}
}
bag = newBag;
capacity = newCapacity;
return deleted;
}
@Override
public String toString() {
String result = "Bag: ";
for (int i = 0; i < capacity; i++)
result += bag[i] + " ";
return result;
}
}
一个更简单的 delete
实现是可能的,允许“删除”数组中等于给定 item
的 所有 条目并移动剩余的条目高效到最前面:
public boolean delete(int item) {
System.out.println("deleting " + item); // for debug purposes
int oldCapacity = capacity;
for (int i = 0, j = 0; i < oldCapacity; i++) {
if (bag[i] != item) {
bag[j++] = bag[i];
} else {
capacity--;
}
}
System.out.println("new capacity = " + capacity); // for debug
// or use Arrays.fill(bag, capacity, oldCapacity, -1); instead of the loop
for (int i = capacity; i < oldCapacity; i++) {
bag[i] = -1; // mark free entries with -1 in the tail
}
return oldCapacity == capacity;
}
此外,如果在循环中使用多重连接,则方法 toString
应使用 StringBuilder
,或者为简洁起见,以下方法 print
使用 Arrays
中的实用方法可能是实施:
public void print() {
System.out.println(Arrays.toString(Arrays.copyOf(bag, capacity)));
}
测试:
IntBag ibag = new IntBag(10);
ibag.add(1);
ibag.add(3);
ibag.add(3);
ibag.add(2);
ibag.add(1);
ibag.print();
ibag.delete(2);
ibag.print();
ibag.delete(1);
ibag.print();
输出:
[1, 3, 3, 2, 1]
deleting 2
new capacity = 4
[1, 3, 3, 1]
deleting 1
new capacity = 2
[3, 3]
更新
只“删除”第一个条目而不创建新数组的实现方式如下:
- 跳过所有元素,直到检测到
item
或到达 bag
的结尾
- 如果找到
item
,则将剩余元素移位1,将-1写入最后一个元素,returntrue
- return
false
否则
public boolean deleteFirst(int item) {
System.out.println("deleting first " + item);
int id = 0;
while (id < capacity && bag[id] != item) id++;
if (id < capacity && bag[id] == item) {
while (++id < capacity) {
bag[id - 1] = bag[id];
}
bag[--capacity] = -1;
return true;
}
return false;
}
测试:
IntBag ibag = new IntBag(10);
ibag.add(1); ibag.add(3); ibag.add(1); ibag.add(2); ibag.add(1);
ibag.print();
ibag.deleteFirst(1); ibag.print();
ibag.deleteFirst(1); ibag.print();
ibag.deleteFirst(1); ibag.print();
输出:
[1, 3, 1, 2, 1]
deleting first 1
[3, 1, 2, 1]
deleting first 1
[3, 2, 1]
deleting first 1
[3, 2]
我正在从事这个允许我在数组中添加和删除元素的项目。当我删除数组中的元素时,space 中会有一个零,代码应该在删除的值之后移动值以取代它的位置。例如:在数组 {1, 2, 3, 4, 5} 中。我选择删除 3。我的输出应该是 {1, 2, 4, 5}。相反,我的输出是 {1, 2, 5, 4}。有人可以帮我弄清楚为什么会那样做吗?以及如何纠正?
import java.util.Scanner;
import java.util.Arrays;
public class IntBag2 {
private static final int INITIAL_SIZE = 20;
private static int[] bag;
private int capacity;
public IntBag2() {
bag = new int[INITIAL_SIZE];
}
public IntBag2(int capacity) {
bag = new int[capacity];
}
public boolean add(int item) {
if (capacity == bag.length)
return false;
bag[capacity++] = item;
return true;
}
public boolean delete(int item) {
for (int i = 0; i < capacity; i++) {
if (bag[i] == item) {
bag[i] = bag[--capacity];
return true;
}
}
return false;
}
@Override
public String toString() {
String result = "Bag: ";
for (int i = 0; i < capacity; i++)
result += bag[i] + " ";
return result;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
IntBag2 intBag = new IntBag2();
boolean done = false;
while (!done) {
System.out.println("1. Add an Item to the Array");
System.out.println("2. Delete an item in the Array");
System.out.println("3. toString");
switch (input.nextInt()) {
case 1:
System.out.println("Add an Item to the Array");
System.out.println(intBag.add(input.nextInt()));
break;
case 2:
System.out.println("Delete Item of Array");
System.out.println(intBag.delete(input.nextInt()));
break;
case 3:
System.out.println("toString");
System.out.println(intBag.toString());
break;
}
}
input.close();
}
}
使用 bag[i] = bag[--capacity];
行,您基本上是在获取数组中的最后一项并将其放置在已删除项的位置。
鉴于您使用的是 int[]
(而不是 Integer[]
),我们无法将数组的索引分配为 null
。我们能做的最好的就是分配它 -1
或创建一个新数组。
我决定从头开始创建一个新数组。以下内容可以解决问题。
public class IntBag2 {
private static final int INITIAL_SIZE = 20;
private static int[] bag;
private int capacity;
public IntBag2() {
bag = new int[INITIAL_SIZE];
}
public IntBag2(int capacity) {
bag = new int[capacity];
}
public boolean add(int item) {
if (capacity == bag.length)
return false;
bag[capacity++] = item;
return true;
}
public boolean delete(int item) {
int[] newBag = new int[capacity];
int newCapacity = capacity;
boolean deleted = false;
for (int i = 0, j = 0; i < capacity; i++) {
if (bag[i] == item && !deleted) {
deleted = true;
newCapacity = capacity - 1;
} else {
newBag[j++] = bag[i];
}
}
bag = newBag;
capacity = newCapacity;
return deleted;
}
@Override
public String toString() {
String result = "Bag: ";
for (int i = 0; i < capacity; i++)
result += bag[i] + " ";
return result;
}
}
一个更简单的 delete
实现是可能的,允许“删除”数组中等于给定 item
的 所有 条目并移动剩余的条目高效到最前面:
public boolean delete(int item) {
System.out.println("deleting " + item); // for debug purposes
int oldCapacity = capacity;
for (int i = 0, j = 0; i < oldCapacity; i++) {
if (bag[i] != item) {
bag[j++] = bag[i];
} else {
capacity--;
}
}
System.out.println("new capacity = " + capacity); // for debug
// or use Arrays.fill(bag, capacity, oldCapacity, -1); instead of the loop
for (int i = capacity; i < oldCapacity; i++) {
bag[i] = -1; // mark free entries with -1 in the tail
}
return oldCapacity == capacity;
}
此外,如果在循环中使用多重连接,则方法 toString
应使用 StringBuilder
,或者为简洁起见,以下方法 print
使用 Arrays
中的实用方法可能是实施:
public void print() {
System.out.println(Arrays.toString(Arrays.copyOf(bag, capacity)));
}
测试:
IntBag ibag = new IntBag(10);
ibag.add(1);
ibag.add(3);
ibag.add(3);
ibag.add(2);
ibag.add(1);
ibag.print();
ibag.delete(2);
ibag.print();
ibag.delete(1);
ibag.print();
输出:
[1, 3, 3, 2, 1]
deleting 2
new capacity = 4
[1, 3, 3, 1]
deleting 1
new capacity = 2
[3, 3]
更新
只“删除”第一个条目而不创建新数组的实现方式如下:
- 跳过所有元素,直到检测到
item
或到达bag
的结尾 - 如果找到
item
,则将剩余元素移位1,将-1写入最后一个元素,returntrue
- return
false
否则
public boolean deleteFirst(int item) {
System.out.println("deleting first " + item);
int id = 0;
while (id < capacity && bag[id] != item) id++;
if (id < capacity && bag[id] == item) {
while (++id < capacity) {
bag[id - 1] = bag[id];
}
bag[--capacity] = -1;
return true;
}
return false;
}
测试:
IntBag ibag = new IntBag(10);
ibag.add(1); ibag.add(3); ibag.add(1); ibag.add(2); ibag.add(1);
ibag.print();
ibag.deleteFirst(1); ibag.print();
ibag.deleteFirst(1); ibag.print();
ibag.deleteFirst(1); ibag.print();
输出:
[1, 3, 1, 2, 1]
deleting first 1
[3, 1, 2, 1]
deleting first 1
[3, 2, 1]
deleting first 1
[3, 2]