数据结构探险——链表篇

@这篇文档是由C++代码实现的线性表也就是链表

在这里插入图片描述

首先介绍一下链表的存储过程,如上图。每个结点分为data的数据域和next的指针域,单链表的第一个结点之前附设的一个结点称之为头结点。头结点的数据域可以不存储任何信息,也可存储如线性表的长度等类的附加信息,头结点的指针域存储指向第一个结点的指针。

本文是以Visual Studio中新建的C++win32的控制台应用程序实现的,其中建立了头文件和源文件以及实现main()的demo文件,分别是List.h和List.cpp、demo.cpp、Node.h、Node.cpp、Person.h、Person.cpp文件。其中List.h和List.cpp定义了链表的主要数据成员和成员函数,Node.h和Node.cpp一起定义了结点的数据成员,包含了数据域和指针域。Person.h和Person.cpp定义了Node.h中定义个数据域中存储的都是哪种类型的数据,包含了联系人的姓名和电话。最后实现一个电话本存储的功能。

List.h文件

#ifndef LIST_H
#define LIST_H
#include "Node.h"

class List
{
public:
	List();									//构造函数,初始化List的容量空间
	virtual ~List();						//析构函数
	void ClearList();						//清空线性表
	bool ListEmpty();						//判断线性表是否为空
	int ListLength();						//获取线性表长度
	bool GetElement(int i,Node *pNode);		//获取线性表中下标为i的元素,并返回存入e中
	int LocateElement(Node *pNode);			//寻找第一个满足e的数据元素的位序
	bool PriorElement(Node *ce,Node *pe);	//获取指定元素ce的前驱pe
	bool NextElementa(Node *ce, Node *ne);	//获取指定元素ce的后继ne
	bool ListInsert(int i ,Node *pNode);	//在第i个位置插入元素e
	bool ListDelete(int i ,Node *pNode);	//删除第i个位置的元素e
	void ListTraversal();					//遍历线性表
	bool ListInsertHead(Node *pNode);		//从线性表的头部插入数据
	bool ListInsertTail(Node *pNode);		//从线性表的尾部插入数据
private:
	Node *m_pList;
	int m_iLength;
};

#endif

List.cpp文件

#include "List.h"
#include <iostream>
using namespace std;

/*链表构造函数*/
List::List()
{
	m_pList = new Node;
	//m_pList->data = 0;
	m_pList->next = NULL;
	m_iLength = 0;
}

/*链表析构函数*/
List::~List()
{
	ClearList();
	delete m_pList;
	m_pList = NULL;
}

/*将当前链表清空*/
void List::ClearList()
{
	Node *currentNode = m_pList->next;
	while(currentNode != NULL)
	{
		Node *temp = currentNode->next;
		//currentNode = temp;
		//delete temp;
		delete currentNode;//自己想的应该是要释放temp的内存,但是最后结果是释放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;
}

/*获取位序为i的元素的值并返回给e*/
bool List::GetElement(int i,Node *pNode)
{
	if (i>=0 && i< m_iLength)
	{
		Node *currentNode = m_pList;
		for (int k=0; k <=i; k++)
		{
			currentNode = currentNode->next;
		}
		pNode->data = currentNode->data;
		return true;
	} 
	else
	{
		return false;
	}
}

/*在链表内寻找值为e的元素的第一次出现的位序*/
int List::LocateElement(Node *pNode)
{
	Node *currentnode = m_pList->next;
	for (int i=0;i < m_iLength;i++)
	{
		if (currentnode->data == pNode->data)
		{
			return i;
		}
		currentnode = currentnode->next;
	}
	return -1;
}

/*在链表内寻找值为ce的元素的前驱元素并返回给pe*/
bool List::PriorElement(Node *ce,Node *pe)
{
	Node *currentNode = m_pList->next;
	for (int i=0;i < m_iLength;i++)
	{
		if ((currentNode->next)->data == ce->data)
		{
			pe->data = currentNode->data;
			return true;
		} 
		currentNode = currentNode->next;
	}
	return false;
}

/*在链表内寻找值为ce的元素的后继元素并返回给ne*/
bool List::NextElementa(Node *ce, Node *ne)
{
	Node *currentNode = m_pList->next;
	for (int i=0;i < m_iLength-1;i++)
	{
		if (currentNode->data == ce->data)
		{
			ne->data = (currentNode->next)->data;
			return true;
		} 
		currentNode = currentNode->next;
	}
	return false;
}

/*在链表内下标为i的位置插入元素e*/
bool List::ListInsert(int i ,Node *pNode)
{
	if (i<0 || i>m_iLength)				//一定要注意下标位置从0开始一直到链表的长度值。0的位置就是头结点和第一个结点之间的位置,
										//1是第一个节点和第二个结点之间的位置,依次类推,m_iLength的位置应该是最后一个结点的后面。
	{
		return false;
	} 
	else
	{
		Node *currentNode = m_pList;
		for(int k=0; k<i;k++)
		{
			currentNode = currentNode->next;
		}
		//循环完之后currentNode中存放的应该是第i个结点,所要插入元素的位置是在第i个元素的后面。
		//所以只需将新元素的指针域指向第i+1个元素,将第i个元素的指针域指向新元素
		Node *newNode2 = new Node;
		if (newNode2 == NULL)
		{
			return false;
		}
		newNode2->data = pNode->data;
		newNode2->next = currentNode->next;
		currentNode->next = newNode2;
		m_iLength++;
		return true;
	}
}

/*删除链表内的下标为i的元素*/
bool List::ListDelete(int i ,Node *pNode)
{
	if (i<0 || i>=m_iLength)

	{
		return false;
	} 
	else
	{
		Node *currentNode = m_pList;

		//自己的方法
		for(int k=0; k<i; k++)
		{
			currentNode = currentNode->next;
		}
		pNode->data = (currentNode->next)->data;
		currentNode->next = (currentNode->next)->next;   //最主要的操作就是将删除的第i个元素的前驱元素的指针域指向,第i个元素的后继元素
		

		//视频的方法
		//Node *currentNodeBefore = NULL;
		//for (int k=0; k <=i; k++)
		//{
		//	currentNodeBefore = currentNode;
		//	currentNode = currentNode->next;
		//}
		//currentNodeBefore->next = currentNode->next;
		//pNode->data = currentNode->data;

		m_iLength--;
		return true;
	}
}

/*遍历链表内的所有元素并且打印出来*/
void List::ListTraversal()
{
	if (ListEmpty())
	{
		cout << "该线性表为空!" <<endl;
	} 
	else
	{
		Node *currentNode = m_pList->next;
		for (int i=0;i < m_iLength;i++)
		{
			cout << currentNode->data <<endl;
			currentNode = currentNode->next;
		}
		delete currentNode;
		currentNode = NULL;
	}
}

/*从链表的头部插入数据元素pNode*/
bool List::ListInsertHead(Node *pNode)
{
	Node *temp = m_pList->next;
	Node *newnode = new Node;
	if (newnode == NULL)
	{
		return false;
	}
	newnode->data = pNode->data;
	newnode->next = temp;
	m_pList->next = newnode;
	m_iLength++;
	return true;
}

/*从链表的尾部插入数据元素pNode*/
bool List::ListInsertTail(Node *pNode)
{
	Node *currendnode = m_pList;
	while(currendnode->next != NULL)
	{
		currendnode = currendnode->next;
	}
	Node *newnode1 = new Node;
	if (newnode1 == NULL)
	{
		return false;
	}
	newnode1->data = pNode->data;
	currendnode->next = newnode1;
	newnode1->next = NULL;
	m_iLength++;
	return true;
}

Node.h文件

#ifndef NODE_H
#define NODE_H
#include "Person.h"

class Node
{
public:
	Person data;
	Node* next;
	void printNode();
};

#endif

Node.cpp文件

#include "Node.h"
#include <iostream>
using namespace std;

void Node::printNode()
{
	cout << data.name << endl;
	cout << data.phone << endl;
}

Person.h文件

#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <ostream>
using namespace std;

class Person
{
	friend ostream &operator<<(ostream &out, Person &person);
public:
	string name;
	string phone;
	Person &operator = (Person &person);
	bool operator == (Person &person);
};

#endif

Person.h文件

#include "Person.h"

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;
	} 
	else
	{
		return false;
	}
}

demo.cpp文件

#include "List.h"
#include "Node.h"
#include <iostream>
using namespace std;


int menu()
{
	cout << "功能菜单:" << endl;
	cout << "1.新建联系人" << endl;
	cout << "2.删除联系人" << endl;
	cout << "3.浏览通讯录" << endl;
	cout << "4.退出通讯录" << endl;
	cout << "请输入:";
	int order = 0;
	cin >> order;
	return order;
}


void createPerson(List *pList)
{
	Node node;
	//Person person;
	cout << "请输入联系人姓名:" << endl;
	cin >> node.data.name;
	cout << "请输入联系人电话:" << endl;
	cin >> node.data.phone;
	pList->ListInsertTail(&node);
}

void deletePerson(List *pList)
{
	Node node;
	cout << "请输入要删除的联系人姓名:" << endl;
	cin >> node.data.name;
	int i =pList->LocateElement(&node);
	pList->ListDelete(i,&node);
	cout << "删除联系人:" << node.data.name << endl;
}


int main(void)
{
	int userOrder = 0;
	List *pList = new List();
	while(userOrder !=4)
	{
		userOrder = menu();
		switch(userOrder)
		{
		case 1:
			cout << "用户指令—新建联系人:" <<endl;
			createPerson(pList);
			break;
		case 2:
			cout << "用户指令—删除联系人:" <<endl;
			deletePerson(pList);
			break;
		case 3:
			cout << "用户指令—浏览通讯录:" <<endl;
			pList->ListTraversal();
			break;
		case 4:
			cout << "用户指令—退出通讯录:" <<endl;
			break;
		}
	}
	
	
	//Node node1;
	//node1.data.name = "张三";
	//node1.data.phone = "13838483848";

	//Node node2;
	//node2.data.name = "李四";
	//node2.data.phone = "18039453845";

	//List *pList = new List();

	//Node *node1 = new Node;
	//node1->data = 1;
	//pList->ListInsertTail(&node1);

	//Node node2;
	//node2.data = 2;
	//pList->ListInsertHead(&node2);

	//Node *node3 = new Node;
	//node3->data = 3;
	//pList->ListInsertTail(node3);

	//Node node4;
	//node4.data = 4;
	//pList->ListInsertHead(&node4);

	//Node node5;
	//node5.data = 5;
	//pList->ListInsert(2,&node5);

	//cout << "遍历线性表内的所有元素为:" << endl;
	//pList->ListTraversal();

	//Node node6;
	//pList->GetElement(2,&node6);
	//cout << "位序为2的元素为:" << endl;
	//cout << node6.data << endl;

	//cout << "删除位序为2的元素为:" << endl;
	//pList->ListDelete(2,&node6);
	//cout << node6.data << endl;

	//cout << "遍历线性表内的所有元素为:" << endl;
	//pList->ListTraversal();
	//cout << "该线性表的长度为:" << endl;
	//pList->ListLength();

	//Node node7;
	//Node node8;
	//Node node9;
	//node7.data = 2;
	//pList->PriorElement(&node7,&node8);
	//pList->NextElementa(&node7,&node9);
	//cout << "值为2的前驱元素为:" << node8.data << endl;
	//cout << "值为2的元素的位序为:" << pList->LocateElement(&node7) << endl;
	//cout << "值为2的后继元素为:" << node9.data << endl;

	//pList->ClearList();
	//cout << "遍历线性表内的所有元素为:" << endl;
	//pList->ListTraversal();

	delete pList;
	pList = NULL;
	
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值