直接上代码了。。
List.h
#ifndef LIST_H
#define LIST_H
#include"Node.h"
//class Node;
class List
{
public:
List();
~List();
void clearList();//清空表
bool listEmpty();//判断是否为空表
int listLength();//表元素长度
bool getNode(int i,Node *e);//获得第i(0开始)个元素赋值给e
int locateNode(Node *e);//找出与e相等的元素并返回元素下标
bool priorNode(Node* currentNode,Node* preNode);//用指针类型可以节省空间,找到和当前元素一样的值的元素的前一个元素赋给preNode
bool nextNode(Node* currentNode,Node* nextNode);
bool listInsert(int i,Node*e);//在i位置插入元素
bool listDelete(int i,Node *e);//删除i位置元素
void listTraverse();//遍历
bool listInsertHead(Node* e);
bool listInsertTail(Node* e);
private:
Node *m_pList;
int m_iLength;
};
#endif
List.cpp
#include"List.h"
#include"Node.h"
#include<iostream>
using namespace std;
List::List()
{
m_pList = new Node;
//m_pList->data = 0;
m_pList->next = NULL;//空链表表示只有一个表头
m_iLength = 0;
cout << "List<Node>::List(int size)" << endl;
}
List::~List()//表头也被释放了
{
clearList();
delete m_pList;
m_pList = NULL;
}
void List::clearList()//回到空链表状态(只剩表头)
{
if(!listEmpty()){
Node *p1,*p2;
p1 = m_pList->next;
while(p1 != NULL){
p2 = p1->next;
delete p1;
p1 = p2;
}
m_pList->next = NULL;
m_iLength = 0;
}
}
bool List::listEmpty()
{
if(m_iLength == 0)return true;
return false;
}
int List::listLength()
{
return m_iLength;
}
bool List::getNode(int i,Node *e)
{
if((i >= 0)&&(m_iLength > i)){
//*e = m_pList[i];
Node *currentNode = m_pList->next;
for(int j = 0;j < i;j++){
currentNode = currentNode->next;
}
e->data = currentNode->data;
return true;
}else{
return false;
}
}
int List::locateNode(Node *e)
{
//int i;
//for(i = 0;i < m_iLength;i ++){
// if(*e == m_pList[i]){
// return i;
// }
//}
int index = 0;
Node *currentNode = m_pList->next;
while((currentNode != NULL) && (currentNode->data != e->data)){
currentNode = currentNode->next;
index++;
}
if(currentNode == NULL){
cout << "没有相同的元素" << endl;
return -1;//下标不会小于0
}else{
return index;
}
}
bool List::priorNode(Node* currentNode,Node* preNode)
{
int temp = locateNode(currentNode);//取名temp因为它是一个临时的返回值
Node *p = m_pList->next;
if(temp > 0){
for(int i = 0;i < temp-1;i++){
p = p->next;
}
preNode->data = p->data;
return true;
}else{
return false;
}
}
bool List::nextNode(Node* currentNode,Node* nextNode)
{
int temp = locateNode(currentNode);//取名temp因为它是一个临时的返回值
Node *p = m_pList->next;
if((temp >= 0)&&(temp < m_iLength-1)){
for(int i = 0;i < temp+1;i++){
p = p->next;
}
nextNode->data = p->data;
return true;
}else{
return false;
}
}
void List::listTraverse()
{
if(!listEmpty()){
Node *p = m_pList->next;
while(p != NULL){
cout << p->data;
cout << endl;
p = p->next;
}
cout << endl;
}else{
cout << "空表!" << endl;
}
}
bool List::listInsert(int i,Node*e)
{
if((i >= 0)&&(i <= m_iLength)){
Node *newNode = new Node;
if(newNode == NULL){
return false;
}
newNode->data = e->data;
Node *temp = m_pList;
for(int j = 0;j < i;j++){
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
m_iLength ++;//别忘了!
return true;
}else{
return false;
}
}
bool List::listDelete(int i,Node *e)
{
if((i >= 0)&&(i < m_iLength)&&(!listEmpty())){
Node *temp = m_pList;
for(int j = 0;j < i;j++){
temp = temp->next;
}
Node *delNode = temp->next;
temp->next = temp->next->next;
e->data = delNode->data;
delete delNode;
delNode = NULL;
m_iLength --;
return true;
}else{
return false;
}
}
bool List::listInsertHead(Node* e)//只用e的data
{
Node *newNode = new Node;
if(newNode == NULL){//申请失败
return false;
}
newNode->data = e->data;
newNode->next = m_pList->next;
m_pList->next = newNode;
m_iLength ++;//别忘了!
return true;
}
bool List::listInsertTail(Node* e)
{
Node *p = m_pList;
while(p->next != NULL){
p = p->next;
}
Node *newNode = new Node;//申请新内存
while(newNode == NULL){
return false;
}
p->next = newNode;
newNode->data = e->data;//只是将e的data赋值过来,而不是直接将e加入
newNode->next = NULL;
m_iLength ++;//别忘了!
return true;
}
Node.h
#ifndef NODE_H
#define NODE_H
#include"Person.h"//实验后发现比下一句好,如果用下一句,则Person data;会显示不允许使用不完整的定义
//class Person;
class Node
{
public://为了方便都定义在public下
Person data;
Node *last;
Node *next;
//Node();直接用默认
//~Node();
};
#endif
Person.h
#ifndef PERSON_H
#define PERSON_H
#include<string>//因为有定义string类
#include<ostream>//因为用到了ostream,不写iostream能方便编译
using namespace std;
class Person
{
friend ostream& operator << (ostream&, Person&);
public:
bool operator != (Person&);
//Person operator = (Person&);//不重载=也不会报错,因为person里面就name和phone两个简单的string类变量,但如果person有指针类变量,就必须要重载了,浅拷贝没有自己定义的深拷贝安全
string name;
string phone;
};
#endif
Person.cpp
#include"Person.h"
ostream& operator << (ostream& out, Person& person)//是一个全局函数,写在全局的任意位置都可以
{
out << "姓名:" << person.name << endl;
out << "电话:" << person.phone;
return out;
}
bool Person::operator != (Person& person)
{
if( (this->name == person.name) || (this->phone == person.phone) ){//非严格相等,只要名字和电话中有一者是相同的,则判断为两个person相同并返回false
return false;
}
return true;
}
demo.cpp
#include<iostream>
#include<stdlib.h>
#include"List.h"
#include"Node.h"
#include"Person.h"
using namespace std;
//线性表(包括顺序表和链表)——动态链表 c++实现
//链表优点:改善了顺序表缺陷(插入和删除元素时,元素后面的所有元素都要移动)
//缺点:寻址取数据较麻烦
//以通讯录为例
int menu()
{
cout << "通过录功能" << endl;
cout << "1.新建联系人" << endl;
cout << "2.删除联系人" << endl;
cout << "3.浏览通讯录" << endl;
cout << "4.退出通讯录" << endl;
cout << "请输入:" << endl;
int order = 0;
cin >> order;
return order;
}
void creatPerson(List *pList)
{
Node node;
Person person;
cout << "输入姓名:" << endl;
cin >> person.name;
cout << "输入电话:" << endl;
cin >> person.phone;
node.data = person;
pList->listInsertTail(&node);//create函数调用完后node就会被释放掉,所以insert函数定义里面一定是只取node的data的深拷贝方法。
}
void deletePerson(List *pList)
{
Node node;
Person person;
cout << "待删人的姓名(不知道请输入0):" << endl;
cin >> person.name;
cout << "待删人的电话(不知道请输入x):" << endl;
cin >> person.phone;
node.data = person;
int delIndex = pList->locateNode(&node);
pList->listDelete(delIndex,&node);
}
int main(){
int userOrder = 0;
List *pList = new List();
while(userOrder != 4)//不退出就可以一直循环
{
userOrder = menu();
switch (userOrder)
{
case 1:
cout << "用户指令--->>新建联系人:" << endl;
creatPerson(pList);
break;
case 2:
cout << "用户指令--->>删除联系人:" << endl;
deletePerson(pList);
break;
case 3:
cout << "用户指令--->>浏览通讯录:" << endl;
pList->listTraverse();
break;
case 4:
cout << "用户指令--->>退出通讯录:" << endl;
break;
default:
break;
}
}
delete pList;
pList = NULL;
system("pause");
return 0;
}