数据结构课程设计(基于二叉排序树的身份证管理系统)

时间:2024-01-30 18:06:35

题目十六  基于二叉排序树的身份证信息管理系统

问题描述:建立身份证信息管理系统,能够进行身份证信息的录入、查找,保存,要求考虑查找效率,用二叉排序树存储信息

具体功能有:

(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