題目十六 基於二叉排序樹的身份證信息管理系統
問題描述:建立身份證信息管理系統,能夠進行身份證信息的錄入、查找,保存,要求考慮查找效率,用二叉排序樹存儲信息。
具體功能有:
(1)能夠進行身份證號碼及相關信息的錄入,相關信息包括姓名、地址和手機號;
(2)能夠快速進行身份證號碼的查詢,並輸出相關信息;
(3)可以修改身份證號碼對應的其他信息,如姓名、地址;
(4)可以完成身份證信息的刪除。
(5)信息保存到數據文件中。
因為要考慮到查找效率,因此建樹時就建立的AVL樹!!!
使用Dev-c++可以運行
全部代碼
#include<bits/stdc++.h> using namespace std; /*文件的操作*/ ofstream mycout("Information.txt");//c++牛逼 //相關信息的結構體數據結構 struct Person{ string idnumber;//身份證號碼 string name;//姓名 string address;//地址 string phonenumber;//手機號碼 }person; //平衡二叉樹的二叉鏈表節點數據結構 typedef struct BiTNode{ //int height;//節點的高度 Person person;//數據域 struct BiTNode *lchild,*rchild;//指針域 //結構體的初始化 BiTNode() { lchild = rchild = NULL; } }BiTNode, *BiTree; BiTree T;//空樹 BiTree temp;//保存找到的那個id的指針 //獲得樹當前節點的高度 int Get_Height(BiTree T) { if(T == NULL) return 0;//空樹 return max(Get_Height(T->lchild),Get_Height(T->rchild)) + 1;//左右子樹中較高的 + 1 } /* LL型失衡,調整二叉樹需要兩步 第一步:將失衡節點的左子樹的右子樹 變成 失衡節點的左子樹 第二步:失衡節點 變成 失衡節點未發生操作前左子樹的右子樹 */ BiTree LL_Rotation(BiTree T) { BiTree temp; temp = T->lchild;//臨時保存失衡節點的左子樹 T->lchild = temp->rchild;//將失衡節點的左子樹的右子樹 變成 失衡節點的左子樹 temp->rchild = T;//失衡節點變成temp的右子樹 return temp; } /* RR型失衡 RR型的操作和基本相同,只是方向相反 */ BiTree RR_Rotation(BiTree T) { BiTree temp; temp = T->rchild;//臨時保存失衡節點的右子樹 T->rchild = temp->lchild;//將失衡節點的右子樹的左子樹 變成 失衡節點的右子樹 temp->lchild = T;//失衡節點變成temp的左子樹 return temp; } /* LR型失衡 LR型失衡的操作相比於LL型失衡操作相對要復雜一點,需要旋轉兩次才能恢復平衡 第一步:對失衡節點的左子樹進行RR型旋轉 第二步:對失衡節點進行LL型旋轉 */ BiTree LR_Rotation(BiTree T) { T->lchild = RR_Rotation(T->lchild);//對失衡節點的左子樹進行RR型旋轉 return LL_Rotation(T);//對失衡節點進行LL型旋轉 } /* RL失衡 和LR型的旋轉基本相同 */ BiTree RL_Rotation(BiTree T) { T->rchild = LL_Rotation(T->rchild);//對失衡節點的右子樹進行LL型旋轉 return RR_Rotation(T);//對失衡節點進行RR型旋轉 } /* 創建樹,也就是信息的錄入 能夠進行身份證號碼及相關信息的錄入,相關信息包括姓名、地址和手機號 */ BiTree CreateTree(BiTree T, Person person) { if(T == NULL)//空樹 { BiTree temp = new BiTNode; temp->lchild = temp->rchild = NULL; temp->person = person; return temp; } /*身份證長度肯定一樣長,因此也就是比較每一位數字,數字越大越往前靠*/ /*根據字典序來排idnumber*/ /*大於*/ else if(person.idnumber > T->person.idnumber) { T->rchild = CreateTree(T->rchild,person); if(Get_Height(T->rchild) - Get_Height(T->lchild) == 2)//右子樹 - 左子樹 { if(person.idnumber < T->rchild->person.idnumber) T = RL_Rotation(T); else T = RR_Rotation(T); } } /*小於*/ else if(person.idnumber < T->person.idnumber) { T->lchild = CreateTree(T->lchild,person); if(Get_Height(T->lchild) - Get_Height(T->rchild) == 2)//左子樹 - 右子樹 { if(person.idnumber < T->lchild->person.idnumber) T = LL_Rotation(T); else T = LR_Rotation(T); } } else if(person.idnumber == T->person.idnumber) { cout << "輸入有誤,身份證號不應該相同" << endl << endl; return T; } return T; } /* 信息的查找 能夠快速進行身份證號碼的查詢,並輸出相關信息 */ bool SearchTree(BiTree T,string id) { if(T == NULL) { cout << "查找值不存在!" << endl; return false; } else { if(T->person.idnumber == id) { temp = T;//記錄當前節點指針 cout << "姓名為: " << T->person.name << endl; cout << "身份證號為: " << T->person.idnumber << endl; cout << "家庭地址為: " << T->person.address << endl; cout << "電話號碼為: " << T->person.phonenumber << endl; } else if(T->person.idnumber < id)//根據字典序來排大小,如果當前節點的idnumber小於查找的idnumber { SearchTree(T->rchild,id); } else if(T->person.idnumber > id)//根據字典序來排大小,如果當前節點的idnumber大於查找的idnumber { SearchTree(T->lchild,id); } } return true; } bool modificationTree(BiTree T,string id) { /*存在才要修改*/ if(SearchTree(T,id)) { cout << "請輸入你想要修改的信息類型(姓名,地址,手機號碼)" << endl; string s; cin >> s; if(s == "姓名") { cout << "請輸入修改后的值: "; cin >> person.name; temp->person.name = person.name; } else if(s == "地址") { cout << "請輸入修改后的值: "; cin >> person.address; temp->person.address = person.address; } else if(s == "手機號碼") { cout << "請輸入修改后的值: "; cin >> person.phonenumber; temp->person.phonenumber = person.phonenumber; } } else { cout << "查無此人,抱歉" << endl; return false; } return true; } /* 若二叉排序樹T中存在關鍵字等於id的數據元素時,則刪除該數據元素結點, */ /* 並返回TRUE;否則返回FALSE。 */ bool removeTree(BiTree *T,string id) { //從二叉排序樹中刪除關鍵字為id的節點 if(!*T) { cout << "查無此人,無法刪除!" << endl; return false; } else { if(id == (*T)->person.idnumber) { BiTree q,s; if((*T)->rchild == NULL) /* 右子樹空則只需重接它的左子樹(待刪結點是葉子也走此分支) */ { q = *T; *T = (*T)->lchild; free(q); } else if((*T)->lchild == NULL) /* 只需重接它的右子樹 */ { q = *T; *T = (*T)->rchild; free(q); } else /* 左右子樹均不空 */ { q = *T; s = (*T)->lchild; while(s->rchild) /* 轉左,然后向右到盡頭(找待刪結點的前驅) */ { q = s; s = s->rchild; } (*T)->person = s->person; /* s指向被刪結點的直接前驅(將被刪結點前驅的值取代被刪結點的值) */ if(q != (*T)) q->rchild = s->lchild; /* 重接q的右子樹 */ else q->lchild = s->lchild; /* 重接q的左子樹 */ free(s); } } else if(id < (*T)->person.idnumber) return removeTree(&(*T)->lchild,id); else return removeTree(&(*T)->rchild,id); } return true; } /*中序遍歷AVL樹,並打印節點高度*/ void Midorder_Traverse(BiTree T) { if(T != NULL) { Midorder_Traverse(T->lchild); cout << endl; cout << "姓名: " << T->person.name << endl; cout << "身份證號: " << T->person.idnumber << endl;//<< " " << "高度: " << Get_Height(T) << endl; cout << "地址: " <<T->person.address << endl; cout << "手機號碼: " <<T->person.phonenumber << endl; Midorder_Traverse(T->rchild); } return; } /*文件操作*/ void Midorder_TraverseToFile(BiTree T) { if(T != NULL) { Midorder_TraverseToFile(T->lchild); //cout << endl; mycout << "姓名: " << T->person.name << endl; mycout << "身份證號: " << T->person.idnumber << endl;//<< " " << "高度: " << Get_Height(T) << endl; mycout << "地址: " <<T->person.address << endl; mycout << "手機號碼: " <<T->person.phonenumber << endl; Midorder_TraverseToFile(T->rchild); } return; } /*錄入信息的輸入*/ void InformationInput() { char ch; while(true) { cout << "輸入信息?(Y/N): "; cin >> ch; if(ch == 'Y' || ch == 'y') { cout << "請輸入姓名: "; cin >> person.name; cout << "請輸入身份證號: "; cin >> person.idnumber; cout << "請輸入家庭地址: "; cin >> person.address; cout << "請輸入手機號碼: "; cin >> person.phonenumber; T = CreateTree(T,person); } else if(ch == 'N' || ch == 'n') { cout << "錄入結束,謝謝合作!" << endl << endl; return; } else { cout << "關鍵字輸入錯誤,請重新輸入!" << endl; continue; } } } /*查詢信息的輸入*/ void SearchInformationInput() { char ch; while(true) { cout << "是否查找?(Y/N): "; cin >> ch; if(ch == 'Y' || ch == 'y') { cout << "請輸入你想要查找的身份證號碼: "; cin >> person.idnumber; SearchTree(T,person.idnumber); } else if(ch == 'n' || ch == 'N') { cout << "查找結束,祝您愉快!" << endl << endl; return; } else { cout << "關鍵字輸入錯誤,請重新輸入!" << endl; continue; } } } /*修改信息的輸入*/ void modificationInformationInput() { char ch; while(true) { cout << "修改信息?(Y/N): "; cin >> ch; if(ch == 'Y' || ch == 'y') { cout << "請輸入您修改人信息對應的身份證號: "; cin >> person.idnumber; modificationTree(T,person.idnumber); } else if(ch == 'N' || ch == 'n') { cout << "修改操作已經結束,您可以繼續其他操作!" << endl; return; } else { cout << "關鍵字輸入錯誤,請重新輸入!" << endl; continue; } } } //身份證及相關信息的刪除 void RemoveIdNumberInformationInput() { char ch; while(true) { cout << "刪除信息?(Y/N): "; cin >> ch; if(ch == 'Y' || ch == 'y') { cout << "請輸入您刪除人信息對應的身份證號: "; cin >> person.idnumber; if(removeTree(&T,person.idnumber)) cout << "刪除成功!" << endl; else cout << "刪除失敗!" << endl; } else if(ch == 'N' || ch == 'n') { cout << "修改操作已經結束,您可以繼續其他操作!" << endl; return; } else { cout << "關鍵字輸入錯誤,請重新輸入!" << endl; continue; } } } int main() { int n = 0; cout << "************************************************************"<< endl; cout << "* 基於二叉排序樹身份證管理系統 *" << endl; cout << "* \t\t1.相關信息的錄入\t\t *" << endl; cout << "* \t\t2.相關信息的查找\t\t *" << endl; cout << "* \t\t3.相關信息的修改\t\t *" << endl; cout << "* \t\t4.相關信息的刪除\t\t *" << endl; cout << "* \t\t5.將相關信息保存到文件中\t\t *" << endl; cout << "* \t\t6.遍歷(將信息輸出在控制台) \t *" << endl; cout << "************************************************************" << endl << endl; cout << "\t ***歡迎使用該系統*** \t\t" << endl; cout << "\t溫馨提示,輸入 -1 用來結束輸入操作哦!\t" << endl << endl; while(n != -1) { cout << "請輸入你想要執行的操作:"; cin >> n; cout << endl; switch (n) { case 1: InformationInput();//建立樹,也就是信息的建立 break; case 2: SearchInformationInput();//相關信息的查找 break; case 3: modificationInformationInput();//相關信息的修改 break; case 4: RemoveIdNumberInformationInput();//身份證信息的刪除 break; case 5: Midorder_TraverseToFile(T);//將信息保存在文本文檔中 break; case 6: cout << "*****該系統中的用戶列表如下*****" << endl; Midorder_Traverse(T);//前序遍歷 cout << endl; cout << "********************************" << endl; break; } if(n != -1) { cout << endl; cout << "*****輸入-1用來結束輸入操作哦!*****" << endl; cout << "1.相關信息的錄入" << endl; cout << "2.相關信息的查找" << endl; cout << "3.相關信息的修改" << endl; cout << "4.相關信息的刪除" << endl; cout << "5.將相關信息保存到文件中" << endl; cout << "6.遍歷" << endl << endl; } else { cout << "***您的操作已經結束,祝您愉快!***" << endl; } } return 0; }
