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")@Overrideprotected 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() {@Overridepublic 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"><Spinnerandroid:id="@+id/startStation"android:layout_width="match_parent"android:layout_height="wrap_content"android:prompt="@string/start_station_prompt" /><Spinnerandroid:id="@+id/endStation"android:layout_width="match_parent"android:layout_height="wrap_content"android:prompt="@string/end_station_prompt" /><EditTextandroid:id="@+id/ticketQuantity"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="购票数量"android:inputType="number" /><Buttonandroid:id="@+id/buyButton"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="立即购票" /><TextViewandroid: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) {//辅助指针指向第一个元素,辅助指针不断向后指,直到遇到NULLnode_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;}