原代碼三大致命缺陷
- 棧上構建樹節點:`node a;` 為局部變量,函數返回後內存失效,指針懸空。必須 `new` 分配堆內存。
- 遞歸調用 `login()` 導致棧溢出:用戶名錯誤時 `login()` 直接遞歸,無基例終止,連續輸入錯誤即棧溢出。改用循環。
- 手動 `delete` 順序錯誤且重複釋放:`delete a.left->left` 後 `a.left->left = 0`,隨後 `delete a.left` 會二次釋放已釋放內存。應遞歸後序釋放。
修正版核心結構
class Node {
public:
string name, keyword;
Node *left, *right;
Node(string n, string k) : name(n), keyword(k), left(nullptr), right(nullptr) {}
};
Node* buildTree() { // 堆上構建
Node* root = new Node("f", "f");
root->left = new Node("c", "c");
root->left->left = new Node("123", "123");
root->right = new Node("one", "one");
root->right->right = new Node("wang", "@@110");
return root;
}
void deleteTree(Node* root) { // 後序釋放
if (!root) return;
deleteTree(root->left);
deleteTree(root->right);
delete root;
}
bool search(Node* root, const string& name, const string& pwd) {
while (root) {
if (name < root->name) root = root->left;
else if (name > root->name) root = root->right;
else return root->keyword == pwd;
}
return false;
}
void login() {
Node* root = buildTree();
string user, pass;
while (true) { // 循環代替遞歸
cout << "用戶名 密碼: ";
cin >> user >> pass;
if (search(root, user, pass)) { cout << "登錄成功\n"; break; }
// 此處可增加重試邏輯,區分用戶名/密碼錯誤
cout << "失敗,重試\n";
}
deleteTree(root);
}
關鍵修復點總結
- 所有樹節點 `new` 分配,統一 `deleteTree` 遞歸釋放。
- 登錄邏輯改為 `while(true)` 循環,避免棧增長。
- 查找函數返回 `bool` 簡化流程,移除引用參數。
- 輸入使用 `cin >> user >> pass` 自動分割空白。< /li>