节点关系

node.h

#pragma once
class MM;
class Node{
public:
	Node();
	Node(MM *data);
	Node(MM *data,Node* next);
	Node*& getNext();    //返回指针的引用,用于访问它里面的指针
	MM*& getData();      //提供公有接口,用于访问它里面的数据
protected:
	MM *data;
	Node* next;
};

node.cpp 

.h要避免头文件包含(避免头文件的重复包含)---在.cpp中包含头文件即可

头插法实现数据插入---新插入的数据在最前面

#include "node.h"    //用到了Node节点,需要包含头文件node.h 
#include "mm.h"
Node::Node()
{
	this->next = nullptr;//无参构造函数 直接把指针置为空
}

Node::Node(MM* data)
{
	this->data = data;   //把数据做初始化,再把指针置为空或统一采用初始化参数列表的方式
	this->next = nullptr;
}

Node::Node(MM* data, Node* next)
{
	this->data = data;
	this->next = next;
}

Node*& Node::getNext()
{
	return next;
}

MM*& Node::getData()
{
	// TODO: 在此处插入 return 语句
	return data;
}

实现链表增删改查

list.h

#pragma once
#include "mm.h"
#include "node.h"
//无头链表:表头存数据(这里实现的是有头链表操作)
//有头链表:表头不存数据
class list 
{
public:
	list();
	void insertList(MM* data);          //采用头插法插入数据
	void printList();                   //打印链表中的数据
 
	void deleteAppoin(string posData);  //删除链表中的数据,根据姓名做删除
	Node* searchByData(string posData); //查找链表中的数据,根据姓名做查找

	void saveListToFile(const char* fileName); //文件操作,把链表的数据流到文件中
	void readFileToList(const char* fileName); //把文件的数据流到链表中
protected:
	Node* headNode;
	int curSize;    //当前节点个数
};

list.cpp 

删除表头,要改变表头的指向 第一个节点是要删除的节点要 单独处理

处理删除表头的情况

  • 记录当前节点的(表头)下一个节点

  • 释放表头

//删除的是表头
    Node* nextNode = curNode->getNext();
    delete headNode;
    headNode = nextNode;
    this->curSize--;    //删除成功改变size

处理删除链表中某个数据的情况

//删除链表中的数据
    preNode->getNext() = curNode->getNext();
    delete curNode;
    curNode = nullptr;
    this->curSize--;    //删除成功改变size

 list.cpp 

#include "list.h"
#include <iostream>
using namespace std;
list::list()
{
    this->headNode = nullptr;
    this->curSize = 0;
}
//头插法
void list::insertList(MM* data) 
{
    //表头插入
    headNode = new Node(data, headNode);
    this->curSize++;
}
//打印链表
void list::printList()
{
    Node* pmove = headNode;
    cout << "name" << "\t" << "age" << "\t" << "tel" << "\t" << "sex" << endl;
    while (pmove != nullptr) 
    {
        //cout << pmove->getData() << endl;
        pmove->getData()->printMM();
        pmove = pmove->getNext();
    }
}
//删除链表
void list::deleteAppoin(string posData)
{
    Node* preNode = headNode;
    Node* curNode = headNode;
    while (curNode!=nullptr&&curNode->getData()->getName() != posData) 
    {
        preNode = curNode;
        curNode = curNode->getNext();
    }
    if (curNode == nullptr)       //如果链表为空,说明没找到
    {
        cout << "删除失败!" << endl;
    }
    else if (curNode == preNode)  //删除的节点是第一个节点,代表删除表头
    {
        Node* nextNode = curNode->getNext();
        delete headNode;
        headNode = nextNode;
        this->curSize--;
    }
    else 
    {
        preNode->getNext() = curNode->getNext();
        delete curNode;
        curNode = nullptr;
        this->curSize--;         //删除成功改变size
    }
}
//查找链表中数据
Node* list::searchByData(string posData)
{
    Node* pmove = headNode;
    while (pmove!=nullptr&&pmove->getData()->getName() != posData) 
    {
        pmove = pmove->getNext();
    }
    return pmove;
}
//文件操作---从链表流入文件
void list::saveListToFile(const char* fileName)
{
    fstream save(fileName, ios::out);
    Node* pmove = headNode;
    while (pmove != nullptr) 
    {
        pmove->getData()->saveFile(save);
        pmove = pmove->getNext();
    }
    save.close();
}
//文件操作---从文件流入链表
void list::readFileToList(const char* fileName)
{
    fstream read(fileName, ios::in);
    while (1) 
    {
        MM* mm = new MM;
        mm->readFile(read);
        if (read.eof())
            break;
        insertList(mm);
    }
    read.close();
}

文件操作解析

  • 所有数据存在链表中,对链表做封装文件操作

  • 代码中做了数据的修改的地方,就要做一下文件的保存操作---修改成功后、插入、删除

pList->saveListToFile("1.txt");
//文件操作---从链表流入文件  写
void list::saveListToFile(const char* fileName)
{
    fstream save(fileName, ios::out);
    Node* pmove = headNode;
    while (pmove != nullptr) 
    {
        pmove->getData()->saveFile(save);    //直接调用saveFile()
        pmove = pmove->getNext();
    }
    save.close();
}
//文件操作---从文件流入链表  读
void list::readFileToList(const char* fileName)
{
    fstream read(fileName, ios::in);
    while (1) 
    {
//因为存的是指针,所以每个数据都要new一个对象出来,要有无参构造函数
        MM* mm = new MM;  
        mm->readFile(read);//把数据读到链表中去
//最后一个读取不应该把数据读到链表中(多读了一次),否则会有乱码
        if (read.eof())  
            break;
        insertList(mm);    //把对象存到链表中去
    }
    read.close();
}

测试链表的代码 

int main()
{
        list myList;     //或者new一个对象出来
//插入3个数据
    for(int i=0;i<3;i++){

        myList.insert[i];//需要手动写析构函数

    }
        myList.printlist();  //打印数据
}

 mm.h---通讯录中包含的人物数据:       

  • 单独描述成一个类

  • 提供一些方法能够打印对象,能够打印数据

注意:

  • 需要改链表存储数据的类型---管理的是MM类的数据

  • 链表的删除、查找 由(通过数据做查找)改为 通过姓名做删除、查找

 mm.h

#pragma once
class MM;
class Node{
public:
	Node();
	Node(MM *data);
	Node(MM *data,Node* next);
	Node*& getNext();    
	MM*& getData();      
protected:
	MM *data;    //如果用MM data需要包含头文件#include "mm.h" 否则会报错
	Node* next;
};

//用指针MM* 不会报错 指针只是声明作用 创建对象要已经存在要有创建的过程

 mm.h 

#pragma once
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class MM 
{
public:
	MM(string name, int age, string tel, string sex);
	MM();
	void printMM();
	void saveFile(fstream& file);    //把链表中的数据存到文件中--->流进去
	void readFile(fstream& file);    //读取文件的数据到链表--->流出来
	string& getName();
	int& getAge();
	string& getTel();
	string& getSex();
protected:
	string name;    //通讯录的数据
	int age;
	string tel;
	string sex;
};

 mm.cpp

#include "mm.h"

MM::MM(string name, int age, string tel, string sex):name(name),age(age),tel(tel),sex(sex)
{

}

MM::MM()
{

}

void MM::printMM()
{
	cout << name << "\t" << age << "\t" << tel << "\t" << sex << endl;
}

void MM::saveFile(fstream& file)    //提供保存数据的接口
{
	file << name << " " << age << " " << tel << " " << sex << endl; //直接把数据流到文件中
}
void MM::readFile(fstream& file)
{
	file >> name >> age >> tel >> sex;    //分别流到name,age中,流出来忽视空格
}

string& MM::getName()
{
	return name;
}

int& MM::getAge()
{
	// TODO: 在此处插入 return 语句
	return age;
}

string& MM::getTel()
{
	// TODO: 在此处插入 return 语句
	return tel;
}

string& MM::getSex()
{
	// TODO: 在此处插入 return 语句
	return sex;
}

 MMSystem.h---实现通讯录人物增删改查功能的函数

#pragma once
#include "list.h"
class MMSystem
{
public:
	MMSystem();        
	void MakeMenu();   //菜单
	void KeyDown();    //交互处理
	void insertMM();   //插入数据(查找数据、删除数据也可以封装成函数)

	list*& getPList(); //提供接口访问属性pList
protected:
	list* pList;
};

在当前文件夹中新建一个1.txt 文本文档---用于处理链表流出来的数据把数据流到链表中

MMSystem.cpp

#include "MMsystem.h"

MMSystem::MMSystem():pList(new list)   //类的组合:以另一个对象为数据成员
{
    pList->readFileToList("1.txt");    //对象创建完后要把存在1.txt中的数据加载到链表中
}

void MMSystem::MakeMenu()
{
    cout << "----------------【通讯录】------------------" << endl;
    cout << "\t\t0.退出系统" << endl;
    cout << "\t\t1.插入数据" << endl;
    cout << "\t\t2.删除数据" << endl;
    cout << "\t\t3.查找数据" << endl;
    cout << "\t\t4.修改数据" << endl;
    cout << "\t\t5.浏览数据" << endl;
    cout << "--------------------------------------------" << endl;
}

void MMSystem::KeyDown()
{
    int userKey = 0;
    //new对象准备的变量
    string name;
    Node* result;    //准备一个指针变量,因为返回的是一个指针变量
    cin >> userKey;
    switch (userKey) 
    {
    case 0:
        exit(0);
        break;
    case 1:
        this->insertMM();
        pList->saveListToFile("1.txt");
        break;
    case 2:
        cout << "请输入需要删除的姓名:";   //这里可以封装成函数处理,类似 insertMM();
        cin >> name;
        pList->deleteAppoin(name);
        pList->saveListToFile("1.txt");
        break;
    case 3:
        cout << "请输入需要查找的姓名:";
        cin >> name;
        result = pList->searchByData(name);
        if (result == nullptr)
        {
            cout << "查无此人!" << endl;
        }
        else 
        {
            cout << "查找信息如下:" << endl;
            result->getData()->printMM();
        }
        break;
    case 4:
        cout << "请输入要修改的姓名:";
        cin >> name;
        result = pList->searchByData(name);   //通过姓名做查找
        if (result == nullptr)
        {
            cout << "查无此人!无法修改" << endl;
        }
        else
        {
            cout << "请输入修改的信息:" << endl;
            cin >> result->getData()->getName()
                >> result->getData()->getAge()
                >> result->getData()->getTel()
                >> result->getData()->getSex();
            cout << "修改成功" << endl;
            pList->saveListToFile("1.txt");
        }
        break;
    case 5:
        pList->printList();
        break;
    }
}
void MMSystem::insertMM()    //new对象准备的变量
{
    string name;
    int age;
    string tel;    //电话
    string sex;    //性别
    cout << "请分别输入姓名、年龄、电话号码、性别:" << endl;
    cin >> name >> age >> tel >> sex;
    pList->insertList(new MM(name, age, tel, sex));
}
list*& MMSystem::getPList()
{
    // TODO: 在此处插入 return 语句
    return pList;
}

 c++管理系统.cpp---主函数部分

#include "MMsystem.h"
#include <cstdlib>
int main() 
{
	MMSystem* pSystem = new MMSystem;
	while (1) 
	{
		pSystem->MakeMenu();
		pSystem->KeyDown();
		system("pause");
		system("cls");
	}
	return 0;
}

更多推荐