jmu-Java-PTA题解 (6.6 - 集合(泛型)-10-GeneralStack) 网安2312陈卓
问题要求
实现一个通用的栈数据结构 GeneralStack,它能处理任意引用类型的数据。具体需求如下:
- 编写 GeneralStack 接口,其操作对任何引用类型的数据都适用。接口定义的方法包括:
- push(item):若 item 为 null,则不入栈并直接返回 null。
- pop():出栈操作,若栈为空则返回 null。
- peek():获取栈顶元素,若栈为空则返回 null。
- empty():判断栈是否为空,若为空返回 true。
- size():返回栈中元素的数量。
- 定义 GeneralStack 的实现类 ArrayListGeneralStack,内部使用 ArrayList 对象存储元素,属性名为 list。同时,实现 toString() 方法,该方法返回 list.toString()。
- 定义 Car 对象,包含私有属性 id 和 name,并使用 Eclipse 自动生成 setter、getter 和 toString 方法。
- 在 main 方法中,根据用户输入的选项(quit、Integer、Double、Car)进行相应操作。若输入 quit 则直接退出;否则,输入整数 m 与 n,m 代表入栈个数,n 代表出栈个数。然后根据选项声明不同类型的栈,进行入栈、出栈操作,并按要求输出结果。
输入格式:
- 输入选项(quit、Integer、Double、Car)。若输入 quit,程序结束。
- 若输入其他选项,接着输入整数 m 和 n。
- 输入 m 个相应类型的数据用于入栈。
输出格式:
- 根据不同选项,输出测试类型(如 Integer Test、Double Test、Car Test)。
- 依次输出入栈和出栈的元素信息。
- 输出栈的 toString() 方法结果。
- 若选项为 Integer 或 Double,输出栈中剩余元素的累加和;若选项为 Car,输出栈中剩余元素的 name 属性。
- 输出栈实现类所实现的接口信息。
输入样例:
Integer
5
2
1 2 3 4 5
Double
5
3
1.1 2.0 4.9 5.7 7.2
Car
3
2
1 Ford
2 Cherry
3 BYD
quit
输出样例:
Integer Test
push:1
push:2
push:3
push:4
push:5
pop:5
pop:4
[1, 2, 3]
sum=6
interface GeneralStack
Double Test
push:1.1
push:2.0
push:4.9
push:5.7
push:7.2
pop:7.2
pop:5.7
pop:4.9
[1.1, 2.0]
sum=3.1
interface GeneralStack
Car Test
push:Car [id=1, name=Ford]
push:Car [id=2, name=Cherry]
push:Car [id=3, name=BYD]
pop:Car [id=3, name=BYD]
pop:Car [id=2, name=Cherry]
[Car [id=1, name=Ford]]
Ford
interface GeneralStack
关键点
- 泛型接口设计:GeneralStack 接口需使用泛型,以支持不同引用类型的数据。
- 泛型类实现:ArrayListGeneralStack 类实现 GeneralStack 接口,内部使用 ArrayList 存储元素,避免类型不安全的强制转换。
- 对象定义:Car 对象需包含必要的属性和方法。
- 输入处理:main 方法根据用户输入的选项进行不同的操作,包括入栈、出栈和结果输出。
解题步骤
第一步:定义通用栈接口
使用泛型定义 GeneralStack 接口,确保接口中的方法能处理任意引用类型的数据。
interface GeneralStack <T> {
public T push(T item);
public T pop();
public T peek();
public boolean empty();
public int size();
public String toString();
}
第二步:实现通用栈接口
创建 ArrayListGeneralStack 类实现 GeneralStack 接口,内部使用 ArrayList 存储元素。
class ArrayListGeneralStack<T> implements GeneralStack<T> {
ArrayList<T> list = new ArrayList<>();
public T push(T item){
if(item == null){
return null;
}
list.add(item);
return item;
}
public T pop(){
if(list.isEmpty()){
return null;
}
T e = list.get(list.size()-1);
list.remove(list.size()-1);
return e;
}
public T peek(){
if(list.isEmpty()){
return null;
}
T e = list.get(list.size()-1);
return e;
}
public boolean empty(){
if(list.size() == 0){
return true;
}
return false;
}
public int size(){
return list.size();
}
@Override
public String toString() {
return list.toString();
}
}
第三步:定义 Car 类
定义 Car 类,包含 id 和 name 属性,并提供相应的 setter、getter 和 toString 方法。
class Car{
private int id;
private String name;
public Car(int id, String name){
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Car [" +
"id=" + id +
", name=" + name +
']';
}
}
第四步:实现 main 方法
在 main 方法中,根据用户输入的选项进行相应的操作,包括入栈、出栈和结果输出。
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String choose = in.next();
if(choose.equals("quit")){
break;
}else{
int m = in.nextInt();
int n = in.nextInt();
ArrayListGeneralStack stack;
switch (choose){
case "Integer":
System.out.println("Integer Test");
stack = new ArrayListGeneralStack<Integer>();
for(int i=0;i<m;i++){
System.out.println("push:" + stack.push(in.nextInt()));
}
for(int i=0;i<n;i++){
System.out.println("pop:" + stack.pop());
}
System.out.println(stack);
int sum = 0;
int number1 = stack.size();
for(int i=0;i<number1;i++){
int e = (int) stack.pop();
sum = sum + e;
}
System.out.println("sum=" + sum);
System.out.println(stack.getClass().getInterfaces()[0]);
break;
case "Double":
System.out.println("Double Test");
stack = new ArrayListGeneralStack<Double>();
for(int i=0;i<m;i++){
System.out.println("push:" + stack.push(in.nextDouble()));
}
for(int i=0;i<n;i++){
System.out.println("pop:" + stack.pop());
}
System.out.println(stack);
double sums = 0;
int number2 = stack.size();
for(int i=0;i<number2;i++){
double e = (double) stack.pop();
sums = sums + e;
}
System.out.println("sum=" + sums);
System.out.println(stack.getClass().getInterfaces()[0]);
break;
case "Car":
System.out.println("Car Test");
stack = new ArrayListGeneralStack<Car>();
for(int i=0;i<m;i++){
Car e = new Car(in.nextInt(), in.next());
System.out.println("push:" + stack.push(e));
}
for(int i=0;i<n;i++){
System.out.println("pop:" + stack.pop());
}
System.out.println(stack);
for(int i=0;i<stack.size();i++){
Car e = (Car)stack.pop();
System.out.println(e.getName());
}
System.out.println(stack.getClass().getInterfaces()[0]);
break;
}
}
}
}
}
整体流程图:

整体代码:
import java.util.*;
interface GeneralStack <T> {
public T push(T item);
public T pop();
public T peek();
public boolean empty();
public int size();
public String toString();
}
class ArrayListGeneralStack<T> implements GeneralStack<T> {
ArrayList<T> list = new ArrayList<>();
public T push(T item){
if(item == null){
return null;
}
list.add(item);
return item;
}
public T pop(){
if(list.isEmpty()){
return null;
}
T e = list.get(list.size()-1);
list.remove(list.size()-1);
return e;
}
public T peek(){
if(list.isEmpty()){
return null;
}
T e = list.get(list.size()-1);
return e;
}
public boolean empty(){
if(list.size() == 0){
return true;
}
return false;
}
public int size(){
return list.size();
}
@Override
public String toString() {
return list.toString();
}
}
class Car{
private int id;
private String name;
public Car(int id, String name){
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Car [" +
"id=" + id +
", name=" + name +
']';
}
}
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String choose = in.next();
if(choose.equals("quit")){
break;
}else{
int m = in.nextInt();
int n = in.nextInt();
ArrayListGeneralStack stack;
switch (choose){
case "Integer":
System.out.println("Integer Test");
stack = new ArrayListGeneralStack<Integer>();
for(int i=0;i<m;i++){
System.out.println("push:" + stack.push(in.nextInt()));
}
for(int i=0;i<n;i++){
System.out.println("pop:" + stack.pop());
}
System.out.println(stack);
int sum = 0;
int number1 = stack.size();
for(int i=0;i<number1;i++){
int e = (int) stack.pop();
sum = sum + e;
}
System.out.println("sum=" + sum);
System.out.println(stack.getClass().getInterfaces()[0]);
break;
case "Double":
System.out.println("Double Test");
stack = new ArrayListGeneralStack<Double>();
for(int i=0;i<m;i++){
System.out.println("push:" + stack.push(in.nextDouble()));
}
for(int i=0;i<n;i++){
System.out.println("pop:" + stack.pop());
}
System.out.println(stack);
double sums = 0;
int number2 = stack.size();
for(int i=0;i<number2;i++){
double e = (double) stack.pop();
sums = sums + e;
}
System.out.println("sum=" + sums);
System.out.println(stack.getClass().getInterfaces()[0]);
break;
case "Car":
System.out.println("Car Test");
stack = new ArrayListGeneralStack<Car>();
for(int i=0;i<m;i++){
Car e = new Car(in.nextInt(), in.next());
System.out.println("push:" + stack.push(e));
}
for(int i=0;i<n;i++){
System.out.println("pop:" + stack.pop());
}
System.out.println(stack);
for(int i=0;i<stack.size();i++){
Car e = (Car)stack.pop();
System.out.println(e.getName());
}
System.out.println(stack.getClass().getInterfaces()[0]);
break;
}
}
}
}
}
思考:在实现通用栈时,使用泛型和不使用泛型会有显著的差异。若不使用泛型,要为每种数据类型单独定义栈类,例如为 Integer 类型和 String 类型分别定义栈类,这样做会导致代码冗余,每种数据类型都需要编写一套相似的栈操作代码,增加了代码量和维护成本,同时也会使类型不安全,如果需要处理新的数据类型,必须手动创建新的栈类,容易出错。而使用泛型则方便许多,它只需编写一次栈操作代码,就可以处理各种类型的数据
同时也避免了运行时的类型转换错误。此外该题中也可以使用LinkedList 替代 ArrayList,LinkedList 是动态扩展,使用LinkedList 会使插入和删除效率增高,但其内存开销大,会导致随机访问效率低。该题同样也可以使用栈(stack)处理,其细节方面在此不再给出,感兴趣的人可以尝试一下或者有想法的人欢迎与我讨论。

浙公网安备 33010602011771号