數據結構課程設計(基於二叉排序樹的身份證管理系統)


題目十六  基於二叉排序樹的身份證信息管理系統

問題描述:建立身份證信息管理系統,能夠進行身份證信息的錄入、查找,保存,要求考慮查找效率,用二叉排序樹存儲信息

具體功能有:

(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;
}
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM