线性表(单链表)
Node.h单一节点定义
#pragma once
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
class Node
{
public:
int data;//数据域
Node* next;//next指针域
void printNode();//打印节点信息
private:
};
void Node::printNode()
{
cout << data << endl;
}
#endif // !NODE_H
List.h链表定义
#pragma once
#ifndef LIST_H
#define LIST_H//引入List.h
#include "Node.h"
using namespace std;
class List
{
public:
List(); //创建线性表
~List(); //销毁线性表
void ClearList(); //清空线性表
bool ListEmpty(); //判断线性表是否为空
int ListLength(); //获取线性表的长度
bool GetElem(int n, Node* pNode); //获取指定元素
int LocateElem(Node* pNode); //寻找第一个满足e的数据元素的位序
bool PriorElem(Node* pCurrentNode, Node* pPreNode);//获取指定元素的前驱
bool NextElem(Node* pCurrentNode, Node* pNextNode);//获取指定元素的后继
bool ListInsert(int n, Node* pNode); //在第n个位置上插入元素
bool ListDelete(int n, Node* pNode); //删除第n个位置上的元素
bool ListInsertHead(Node* pNode); //头插法
bool ListInsertTail(Node* pNode); //尾插法
void ListTraverse(); //便利线性表
private:
Node* m_pList;
int m_iLength;
};
List::List()
{
m_pList = new Node;//node类型的指针new一个Node类型数据
m_pList->data = 0;//默认头节点的数值为0
m_pList->next = NULL;
m_iLength = 0;//设置当前链表长度为0
}
List::~List()
{
ClearList();//执行清理链表的程序,类中声明,类外定义,删除 除了头节点以外的所有结点
delete m_pList;//释放头节点
m_pList = NULL;//设置头节点指针为NULL
}
void List::ClearList()//函数定义
{
Node* currentNode = m_pList->next;//创建currentNode指针指向头节点的下一个节点
while (currentNode != NULL)//循环结束条件:头节点的next指针为空,即只剩下头节点
{
Node* temp = currentNode->next;//C++中指针访问指向数据的成员用->访问,将currentNode所指向数据的next指针赋值给 Node类型的temp指针
delete currentNode;//释放currentNode所指向的内容
currentNode = temp;//将下一节点的指针继续赋值给currentNode
}
m_pList->next = NULL;//m_pList指针所指向内容的next指针指向的内容已被释放,所以设置这个next指针为空(NULL)
}
bool List::ListEmpty()
{
if (m_iLength == 0)
{
return true;
}
else
{
return false;
}
//return m_iLength == 0 ? true : false;
}
int List::ListLength()
{
return m_iLength;
}
bool List::GetElem(int n, Node* pNode)//获得指定位置的节点内容,n负责定位,pNode负责将数据带出来
{
if (n < 0 || n >= m_iLength)//如果n小于0或者大于当前链表的长度,则无法定位
{
return false;//定位失败
}
else
{
Node* currentNode = m_pList;//从头节点的下一个节点开始遍历
for (int i = 0; i <= n; i++)
{
currentNode = currentNode->next;
}
pNode->data = currentNode->data;//将定位的节点数据赋值给pNode的data变量
return true;//返回定位成功
}
}
int List::LocateElem(Node* pNode)//定位元素的位置
{
Node* currentNode = m_pList;//将头节点指针赋值给currentNode指针
int count = 0;
while (currentNode != NULL)
{
currentNode = currentNode->next;//遍历除头节点外的所有节点
if (currentNode->data == pNode->data)
{
return count;//返回count值,即定位的节点位置
}
count++;
}
return -1;//如果没有查找成功则返回-1
}
bool List::PriorElem(Node* pCurrentNode, Node* pPreNode)//pCurrentNode 就是想要查找此节点的前驱节点,用pPreNode指针将内容带出来
{
Node* currentNode = m_pList;//头节点指针赋值给currentNode
Node* tempNode = NULL;
while (currentNode != NULL)//直到当前指针所指内容为空(NULL)
{
tempNode = currentNode;
currentNode = currentNode->next;//回溯到头节点的下一个节点
if (currentNode->data == pCurrentNode->data)//定位到想要查找的节点
{
if (tempNode == m_pList)//如果定位的节点为头节点,则失败,因为头节点没有前驱节点
{
return false;
}
pPreNode->data = tempNode->data;//将数据带出去
return true;
}
}
return false;
}
bool List::NextElem(Node* pCurrentNode, Node* pNextNode)//pCurrentNode 就是想要查找此节点的后继节点,用pNextNode指针将内容带出
{
Node* currentNode = m_pList;
Node* tempNode = NULL;
while (currentNode != NULL)
{
currentNode = currentNode->next;
if (currentNode->data == pCurrentNode->data)//定位到想要查找的节点
{
if (currentNode->next == NULL)//如果定位的节点为尾节点,则失败,因为尾节点没有后继节点
{
return false;
}
pNextNode->data = currentNode->next->data;//将数据带出去
return true;
}
}
return false;
}
void List::ListTraverse()//遍历链表
{
Node* currentNode = m_pList;
while (currentNode->next != NULL)//直到遍历到尾节点
{
currentNode = currentNode->next;
currentNode->printNode();//调用Node类的printNode()方法
}
}
bool List::ListInsert(int n, Node* pNode)//在指定位置插入节点,传入想要插入的节点
{
if (n < 0 || n > m_iLength)
{
return false;
}
else
{
Node* currentNode = m_pList;
for (int i = 0; i < n; i++)
{
currentNode = currentNode->next;
}
Node* newNode = new Node;//内存爆掉的情况,无法new一个Node对象的时候
if (newNode == NULL)
{
return false;
}
newNode->data = pNode->data;
newNode->next = currentNode->next;//newNode指针与currentNode指针所指向内容的next指针指向同一个Node节点
currentNode->next = newNode;//currentNode指针所指向内容的next指针指向newNode
m_iLength++;//更新链表的长度
return true;//返回插入成功
}
}
bool List::ListDelete(int n, Node* pNode)//删除指定位置的节点,并将节点信息带出来
{
if (n < 0 || n >= m_iLength)
{
return false;
}
else
{
Node* currentNode = m_pList;
Node* currentNodeBefore = NULL;
for (int i = 0; i <= n; i++)//一直遍历到指定位置
{
currentNodeBefore = currentNode;
currentNode = currentNode->next;
}
currentNodeBefore->next = currentNode->next;//将当前节点的前驱节点的next指针指向当前节点next指针所指向的内容(即后继节点)
pNode->data = currentNode->data;//将删除节点的内容带出来
currentNode = NULL;//当前节点指向内容为空
m_iLength--;//更新链表长度
return true;//返回删除成功
}
}
bool List::ListInsertHead(Node* pNode)//头插法插入节点
{
Node* temp = m_pList->next;
Node* newNode = new Node;//内存爆掉的情况,无法new一个Node对象的时候
if (newNode == NULL)
{
return false;
}
newNode->data = pNode->data;//将需要插入节点的信息赋值给newNode
newNode->next = temp;//newNode的next指针指向头节点的下一个节点
m_pList->next = newNode;//头节点的next指针指向newNode
m_iLength++;//更新链表长度
return true;//返回插入成功
}
bool List::ListInsertTail(Node* pNode)//尾插法插入节点
{
Node* currentNode = m_pList;
Node* tempNode = NULL;
while (currentNode != NULL)//先遍历到尾节点,最终tempNode为尾节点,currentNode是尾节点的next指针所指向的内容为空(NULL)
{
tempNode = currentNode;
currentNode = currentNode->next;
}
Node* newNode = new Node;
if (newNode == NULL)
{
return false;
}
newNode->data = pNode->data;//将需要插入节点的信息赋值给newNode
newNode->next = NULL;//尾插法,插入节点作为尾节点所以其next指针内容为空(NULL)
tempNode->next = newNode;//未插入前链表的尾节点的next指针指向newNode
m_iLength++;//更新链表长度
return true;//返回插入成功
}
#endif // !LIST_H
List.cpp主函数
#include "List.h"
#include "Node.h"
int main()
{
List* pList = new List();
Node e1, e2, e3, e4, e5, e6, e7, e8;
e1.data = 1;
e2.data = 2;
e3.data = 3;
e4.data = 4;
e5.data = 5;
e6.data = 6;
e7.data = 7;
pList->ListInsertHead(&e1);//头插法插入节点
pList->ListInsertHead(&e2);//头插法插入节点
pList->ListInsertHead(&e3);//头插法插入节点
pList->ListInsertHead(&e4);//头插法插入节点
pList->ListInsertHead(&e5);//头插法插入节点
pList->ListInsertHead(&e6);//头插法插入节点
pList->ListInsertTail(&e1);//尾插法插入节点
pList->ListInsertTail(&e2);//尾插法插入节点
pList->ListInsertTail(&e3);//尾插法插入节点
pList->ListInsertTail(&e4);//尾插法插入节点
pList->ListInsertTail(&e5);//尾插法插入节点
pList->ListInsertTail(&e6);//尾插法插入节点
//pList->ListInsert(6, &e7);//指定位置插入节点
//pList->ListDelete(6, &e8);//指定位置删除节点
pList->NextElem(&e4, &e8);//e8是将后继节点(e5)的内容带出去
pList->ListTraverse();//遍历整个链表的内容
cout << pList->ListLength() << " " << e8.data << endl;//获取整个链表的长度,e8的数据
delete pList;//删除链表,pList会自动执行析构函数,自动释放链表的所有内容
pList = NULL;//指针pList的内容为空
system("pause");
return 0;
}