链表实现的简单模拟通讯录功能
结构图如下:
1.demo.cpp如下:
#include <iostream>
#include <stdlib.h>
#include "List.h"
using namespace std;
/**************************************************/
/*线性表(链表)--通讯录 姓名:电话
功能菜单:
1.新建联系人
2.删除联系人
3.浏览通讯录
4.退出通讯录
请输入:
-------------------------------------
链表中的每个节点Node都有一个数据,这个数据为Person联系人类型,包括姓名、电话。
*/
/**************************************************/
/*菜单选项*/
int menu()
{
cout<<"------------------------"<<endl;
cout<<"功能菜单:"<<endl;
cout<<"1.新建联系人"<<endl;
cout<<"2.删除联系人"<<endl;
cout<<"3.浏览通讯录"<<endl;
cout<<"4.退出通讯录"<<endl;
cout<<"------------------------"<<endl;
cout<<"请输入编号[1-4]:";
int order = 0;
cin>>order;
cout<<endl;
return order;
}
/*创建联系人*/
void creatPerson(List *plist)
{
bool insertFlag = false;
Person person;
Node node;//栈中分配的内存,离开当前函数即被回收
cout<<"请输入姓名:";
cin>>person.name;
cout<<"请输入电话:";
cin>>person.phone;
node.data = person;//重载过
insertFlag = plist->ListTnsertTail(&node);
if (insertFlag)
{
cout<<"#新建成功"<<endl;
}
else
{
cout<<"#新建失败"<<endl;
}
}
//deletePerson2代替deletePerson1
void deletePerson1(List *plist)
{
//未加异常处理
Node node;//栈中分配的内存,离开当前函数即被回收
string delete_name,delete_phone;
int i;
cout<<"请输入要删除联系人的姓名:";
cin>>delete_name;
cout<<"请输入要删除联系人的电话:";
cin>>delete_phone;
node.data.name = delete_name;
node.data.phone = delete_phone;
i = plist->LocateElem(&node);//寻找其位置
plist->ListDelete(i, &node);//删除
}
/*删除联系人*/
void deletePerson2(List *plist)
{
if (plist->ListEmpty())
{
cout<<"#通讯录为空!"<<endl;
}
else
{
Node node;//栈中分配的内存,离开当前函数即被回收
int i;
bool deleteFlag = false;
cout<<"请输入要删除联系人的序号[0-"<<(plist->ListLength()-1)<<"]:";
cin>>i;
deleteFlag = plist->ListDelete(i, &node);//删除
if (deleteFlag)
{
cout<<"#已删除 "<<node.data.name<<" "<<node.data.phone<<endl;
}
else
{
cout<<"#删除失败,请输入正确的序号!"<<endl;
}
}
}
int main(void)
{
List *pList = new List();
int userOrder = 0;
while(userOrder != 4)
{
userOrder = menu();
switch (userOrder)
{
case 1:
cout<<"用户指令->新建联系人:"<<endl;
creatPerson(pList);
break;
case 2:
cout<<"用户指令->删除联系人:"<<endl;
//deletePerson1(pList);
deletePerson2(pList);
break;
case 3:
cout<<"用户指令->浏览通讯录:"<<endl;
pList->ListTraverse();
break;
case 4:
cout<<"用户指令->退出通讯录:"<<endl;
break;
default:
break;
}
}
delete pList;
pList = NULL;
system("pause");
return 0;
}
2.Person.h如下:
#ifndef PERSON_H
#define PERSON_H
#include <iostream>
#include <string>
using namespace std;
class Person
{
friend ostream &operator<<(ostream &out, Person &person);//并不属于Person类,是个全局函数
public:
string name;
string phone;
Person &operator=(Person &person);//=号的重载
bool operator==(Person &person);//==号的重载
};
#endif // !PERSON_H
/****友元函数和成员函数在重载时的区别***/
/*
类的成员函数定义就在类里面,但是类的友元函数定义在其他类里面。
调用的函数不在同一个类中,它们定义也不在同一个类中。
友元函数:具有与类成员函数相同访问权利的“非成员函数”,他可以访问类的私有和保护成员——通过该类对象、对象指针或其引用。
简单且一般的说:运算符重载为类的成员函数,他的参数个数会比“该运算符的操作符”少一,而运算符重载为友元函数时,他的参数与其操作个数是相同的。
*/
3.Person.cpp如下:
#include "Person.h"
//并不属于Person类,是个全局函数,所以不用再其前面加上Person::
ostream &operator<<(ostream &out, Person &person)
{
out<<person.name<<":"<<person.phone;
return out;
}
//=号的重载
Person &Person::operator=(Person &person)
{
this->name = person.name;
this->phone = person.phone;
return *this;
}
//==号的重载
bool Person::operator==(Person &person)
{
if ((this->name == person.name) && (this->phone == person.phone))
{
return true;
}
return false;
}
4.Node.h如下:
#ifndef NODE_H
#define NODE_H
#include "Person.h"
class Node
{
public:
Person data;//联系人 作为数据
Node *next;
void printNode();
};
#endif // !NODE_H
5.Node.cpp如下:
#include "Node.h"
#include <iostream>
using namespace std;
void Node::printNode()
{
cout<<data<<endl;
}
6.List.h如下:
#ifndef LIST_H
#define LIST_H
#include "Node.h"
class List
{
public:
List(); //构造函数
~List(); //析构函数
void ClearList(); //清空
bool ListEmpty(); //判断是否为空
int ListLength(); //获取长度
bool GetElem(int i, Node *pNode); //获取指定位置的节点
int LocateElem(Node *pNode); // 获取指定节点的位置
bool PriorElem(Node *pCurrentNode, Node *pPreNode); //获取指定元素的前驱
bool NextElem(Node *pCurrentNode, Node *pNextNode); //获取指定元素的后继
bool ListInsert(int i, Node *pNode); //在第i个位置插入元素
bool ListDelete(int i, Node *pNode); //删除第i个位置上的元素
void ListTraverse(); //遍历
bool ListInsertHead(Node *pNode); //插入到头的后面
bool ListTnsertTail(Node *pNode); //插入到最后面
private:
Node *m_pList; //存储链表
int m_iLength;
};
#endif // !MYSTACK_H
7.List.cpp如下:
#include "List.h"
#include <iostream>
#include <string.h>
using namespace std;
List::List()
{
m_pList = new Node;//head
//m_pList->data = 0;
m_pList->next = NULL;
m_iLength = 0;
}
//析构函数 删掉头
List::~List()
{
ClearList();
delete m_pList;
}
//除头外 其余的清空
void List::ClearList()
{
Node *currentNode = m_pList->next;
//循环干掉
while(currentNode != NULL)
{
Node *temp = currentNode->next;
delete currentNode;
currentNode = temp;
}
m_pList->next = NULL;
m_iLength = 0;
}
bool List::ListEmpty()
{
return m_iLength == 0 ? true:false;
}
int List::ListLength()
{
return m_iLength;
}
//插入head 节点的后面
bool List::ListInsertHead(Node *pNode)
{
Node *temp = m_pList->next;
Node *newNode = new Node;
if (newNode == NULL)
{
return false;
}
newNode->data = pNode->data;
m_pList->next = newNode;
newNode->next = temp;
m_iLength++;
return true;
}
//插入到最后面
bool List::ListTnsertTail(Node *pNode)
{
Node *currentNode = m_pList;
Node *newNode = new Node;
if (newNode == NULL)
{
return false;
}
//找到最后一个节点
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
}
newNode->data = pNode->data;//把数据拷贝过来
newNode->next = NULL;
currentNode->next = newNode;
m_iLength++;
return true;
}
//在第i个位置插入元素 若是0就插入到head后面,若是m_iLength,就插入到最后面
bool List::ListInsert(int i, Node *pNode)
{
if (i < 0 || i > m_iLength)
{
return false;
}
Node *currentNode = m_pList;
//找到i的前一个节点
for (int k = 0; k < i; k++)
{
currentNode = currentNode->next;
}
Node *newNode = new Node;
if (newNode == NULL)
{
return false;
}
newNode->data = pNode->data;
newNode->next = currentNode->next;
currentNode->next = newNode;
m_iLength++;
return true;
}
//删除第i个位置上的元素
bool List::ListDelete(int i, Node *pNode)
{
if (i < 0 || i >= m_iLength)
{
return false;
}
Node *currentNode = m_pList;
Node *currentNodeBefore =NULL;
//找到i的当前节点
for (int k = 0; k <= i; k++)
{
currentNodeBefore = currentNode;
currentNode = currentNode->next;
}
currentNodeBefore->next = currentNode->next;
pNode->data = currentNode->data;
delete currentNode;
currentNode = NULL;
m_iLength--;
return true;
}
bool List::GetElem(int i, Node *pNode)
{
if (i < 0 || i >= m_iLength)
{
return false;
}
Node *currentNode = m_pList;
//找到i的当前节点
for (int k = 0; k <= i; k++)
{
currentNode = currentNode->next;
}
pNode ->data = currentNode->data;
return true;
}
int List::LocateElem(Node *pNode)
{
Node *currentNode = m_pList;
int count = 0;
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
if (currentNode->data == pNode->data)
{
return count;
}
count++;
}
return -1;
}
/*获取指定元素的前驱*/
//1. 头节点m_pList->next没有前驱
bool List::PriorElem(Node *pCurrentNode, Node *pPreNode)
{
Node *currentNode = m_pList;
Node *currentNodeBefore = NULL;
while (currentNode->next != NULL)
{
currentNodeBefore = currentNode;
currentNode = currentNode->next;
if (currentNode->data == pCurrentNode->data)
{
if (currentNodeBefore == m_pList)
{
return false;
}
pPreNode->data = currentNodeBefore->data;
return true;
}
}
return false;
}
//获取指定元素的后继
bool List::NextElem(Node *pCurrentNode, Node *pNextNode)
{
Node *currentNode = m_pList;
Node *currentNodeNext = NULL;
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
if (currentNode->data == pCurrentNode->data)
{
if (currentNode->next == NULL)
{
return false;
}
currentNodeNext = currentNode->next;
pNextNode->data = currentNodeNext->data;
return true;
}
}
return false;
}
//遍历
void List::ListTraverse()
{
Node *currentNode = m_pList;
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
currentNode->printNode();
}
}
F5后: