尝试AS的手机连接
1.我尝试进行手机连接电脑进行debug,但是我发现我找到的教程做到一半和我的手机配置后者是AS版本不同,不知道为什么IDE会报错不能连接手机。尝试了1.5h,令人烦躁。之后计划多创建几个项目作为备份使用,防止在创建项目时浪费很多时间。在这个过程中,我了解到了虚拟设备对内存的威胁,中间有几次我的程序运行到一半卡退了。还有就是,在运行项目时,一定要先build,再运行!
2.完成了石家庄站地铁的手机端收票计算。
在过程中,我发现站点信息输入错误,逐一进行了校验。之后,MainActivity.java的换乘逻辑错误,换乘时多加了一站。还有,在涉及换乘的站点计算时,换乘后的站点计算消失了,这样就会导致平白无故地少了几站,导致金额算错。下面是我修改上面问题之后的代码:
MainActivity.java
package com.example.myapplication3;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.*;
public class MainActivity extends AppCompatActivity {
private Spinner startStation, endStation;
private EditText ticketQuantity;
private Button buyButton;
private TextView resultText;
private Map<String, List<String>> lines;
private Map<String, String> stationToLine;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startStation = findViewById(R.id.startStation);
endStation = findViewById(R.id.endStation);
ticketQuantity = findViewById(R.id.ticketQuantity);
buyButton = findViewById(R.id.buyButton);
resultText = findViewById(R.id.resultText);
// 初始化地铁线路和站点
initializeLinesAndStations();
// 石家庄地铁站点列表,包含线路信息
List<String> stationsWithLines = new ArrayList<>();
for (Map.Entry<String, String> entry : stationToLine.entrySet()) {
stationsWithLines.add(entry.getKey() + " (" + entry.getValue() + ")");
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, stationsWithLines);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
startStation.setAdapter(adapter);
endStation.setAdapter(adapter);
buyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
calculateAndDisplayTicketPrice();
}
});
}
private void initializeLinesAndStations() {
lines = new HashMap<>();
stationToLine = new HashMap<>();
// 1号线
List<String> line1 = Arrays.asList("西王", "时光街", "长城桥", "和平医院", "烈士陵园", "新百广场", "解放广场", "平安大街", "北国商城", "博物馆", "体育场", "北宋", "谈固", "朝晖桥", "白佛", "留村", "火炬广场", "石家庄东站", "南村", "洨河大桥", "西庄", "东庄", "会展中心", "商务中心", "园博园", "福泽");
lines.put("1号线", line1);
for (String station : line1) {
stationToLine.put(station, "1号线");
}
// 2号线
List<String> line2 = Arrays.asList("柳辛庄", "庄窠·铁道大学", "义堂", "建和桥", "长安公园", "北国商城", "裕华路", "槐中路", "欧韵公园", "元村", "石家庄站", "塔坛", "仓丰路留村", "南位", "嘉华路");
lines.put("2号线", line2);
for (String station : line2) {
stationToLine.put(station, "2号线");
}
// 3号线
List<String> line3 = Arrays.asList("西三庄", "高柱", "柏林庄", "市庄", "市二中", "新百广场", "东里", "西三教", "石家庄站", "汇通路", "孙村", "塔冢", "东王", "南王", "位同", "东二环南路", "西仰陵", "中仰陵", "南豆", "太行南大街", "乐乡");
lines.put("3号线", line3);
for (String station : line3) {
stationToLine.put(station, "3号线");
}
}
private void calculateAndDisplayTicketPrice() {
String startWithLine = startStation.getSelectedItem().toString();
String endWithLine = endStation.getSelectedItem().toString();
// 提取站点名称(去掉线路信息)
String start = startWithLine.split(" \\(")[0];
String end = endWithLine.split(" \\(")[0];
String quantityStr = ticketQuantity.getText().toString();
if (quantityStr.isEmpty()) {
resultText.setText("请输入购票数量");
return;
}
int quantity = Integer.parseInt(quantityStr);
int distance = calculateShortestPath(start, end);
int price = calculatePrice(distance);
int totalPrice = price * quantity;
resultText.setText("购票成功!总金额: " + totalPrice + "元");
}
private int calculateShortestPath(String start, String end) {
if (!stationToLine.containsKey(start) || !stationToLine.containsKey(end)) {
return -1;
}
Map<String, Integer> distances = new HashMap<>();
Map<String, String> lineUsed = new HashMap<>();
for (String station : stationToLine.keySet()) {
distances.put(station, Integer.MAX_VALUE);
}
distances.put(start, 0);
lineUsed.put(start, stationToLine.get(start));
PriorityQueue<String> queue = new PriorityQueue<>(Comparator.comparingInt(distances::get));
queue.add(start);
while (!queue.isEmpty()) {
String current = queue.poll();
if (current.equals(end)) {
break;
}
String currentLine = lineUsed.get(current);
List<String> currentLineStations = lines.get(currentLine);
// 找到当前站点在线路中的位置
int currentIndex = currentLineStations.indexOf(current);
if (currentIndex == -1) {
continue; // 如果当前站点不在当前线路中,跳过
}
// 向前遍历(向线路的下一站)
if (currentIndex < currentLineStations.size() - 1) {
String nextStation = currentLineStations.get(currentIndex + 1);
int newDistance = distances.get(current) + 1;
if (newDistance < distances.get(nextStation)) {
distances.put(nextStation, newDistance);
lineUsed.put(nextStation, currentLine);
queue.add(nextStation);
}
}
// 向后遍历(向线路的上一站)
if (currentIndex > 0) {
String prevStation = currentLineStations.get(currentIndex - 1);
int newDistance = distances.get(current) + 1;
if (newDistance < distances.get(prevStation)) {
distances.put(prevStation, newDistance);
lineUsed.put(prevStation, currentLine);
queue.add(prevStation);
}
}
// 考虑换乘
for (String line : lines.keySet()) {
if (lines.get(line).contains(current) && !line.equals(currentLine)) {
// 换乘增加1站
int newDistance = distances.get(current) + 1;
List<String> transferLineStations = lines.get(line);
int transferIndex = transferLineStations.indexOf(current);
if (transferIndex == -1) {
continue; // 如果当前站点不在换乘线路中,跳过
}
// 向前遍历(向换乘线路的下一站)
if (transferIndex < transferLineStations.size() - 1) {
String nextTransferStation = transferLineStations.get(transferIndex + 1);
if (newDistance < distances.get(nextTransferStation)) {
distances.put(nextTransferStation, newDistance);
lineUsed.put(nextTransferStation, line);
queue.add(nextTransferStation);
}
}
// 向后遍历(向换乘线路的上一站)
if (transferIndex > 0) {
String prevTransferStation = transferLineStations.get(transferIndex - 1);
if (newDistance < distances.get(prevTransferStation)) {
distances.put(prevTransferStation, newDistance);
lineUsed.put(prevTransferStation, line);
queue.add(prevTransferStation);
}
}
}
}
}
return distances.get(end);
}
private int calculatePrice(int distance) {
// 每3站收费1元,不足3站按1元收费
return (distance + 2) / 3;
}
}
布局代码:activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<Spinner
android:id="@+id/startStation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/start_station_prompt" />
<Spinner
android:id="@+id/endStation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="@string/end_station_prompt" />
<EditText
android:id="@+id/ticketQuantity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="购票数量"
android:inputType="number" />
<Button
android:id="@+id/buyButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="立即购票" />
<TextView
android:id="@+id/resultText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="结果将显示在这里"
android:textSize="18sp"
android:gravity="center"
android:padding="16dp" />
</LinearLayout>
3.实现单链表的中间位置插入和单链表的释放
代码如下:
对于链表释放的操作,有两种方法:指针站在自己删自己、指针站在表头依次向后删除
在这个过程中,不可避免的要生成一个临时指针进行备份。要注意的是,不能将指针p的值给临时指针,然后再释放p。因为从图上来看,p和临时指针只是指向一个相同的元素,不能代表那个元素本身。这样操作,临时指针指向的内容也会消失。还有就是,每释放一个节点,就对链表头的总数减去一。在执行这个操作时,有点类似于删除时的操作思想。
void releaseLinkList(LinkList_t* link_table) {
//站在自己删自己
//node_t* p = link_table->head.next;
//node_t* tmp = malloc(sizeof(node_t));
//while (p) {
// tmp = p->next;
// free(p);
// p = tmp;
// link_table->count--;//记得给个数相减
//}
//守住头结点,一直删除头结点后面的元素
node_t* p = &link_table->head;//头结点的首地址
node_t* tmp;
while (p->next) {
tmp = p->next;
p->next = tmp->next;
free(tmp);
link_table->count--;
}
printf("number of node_t: %d\n", link_table->count);
}
void showLinkList(const LinkList_t* link_table) {
//辅助指针指向第一个元素,辅助指针不断向后指,直到遇到NULL
node_t* p = link_table->head.next;//指针类型等于指针类型,不应该多加“&”
printf("link list: %d\n ", link_table->count);
while (p) {
printf("%d\t", p->val);
p = p->next;
}
printf("\n");
}
在中间插入的代码:
1.注意传过来的位置pos是从0开始还是从1开始
2.判断pos传值的合法性,总不能大于链表节点的总数或者是负数
3.还是,找到待插入节点的前一个位置;此处,指针p和下标index关联起来,有助于判断p的位置
4.执行插入操作
int insertLinkListPos(LinkList_t* link_table, int pos, Element_t val) {
//pos:[0...]
if (pos < 0 || pos > link_table->count) {//可以等于,放到最后
printf("insert pos invalid!\n");
return -1;
}
node_t* p = &link_table->head;
/*for (int i = 0; i < pos-1; i++) {
p = p->next;
}*/
//找到索引pos-1的首地址
int index = -1;
while (p&&index<pos-1) {
p = p->next;
index++;
}
node_t* new_node = malloc(sizeof(node_t));
new_node->val = val;
new_node->next = p->next;
p->next = new_node;
link_table->count++;
return 0;
}
浙公网安备 33010602011771号