数据结构 之 线性表中的链表

来源:互联网 发布:东方卫视网络直播回看 编辑:程序博客网 时间:2024/05/16 09:11

直接上代码了。。


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开始)个元素赋值给eint locateNode(Node *e);//找出与e相等的元素并返回元素下标bool priorNode(Node* currentNode,Node* preNode);//用指针类型可以节省空间,找到和当前元素一样的值的元素的前一个元素赋给preNodebool 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相同并返回falsereturn 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;}



原创粉丝点击