线性表分为顺序表(数组)和链表,其中链表包括静态链表(对于有些计算语言没有指针)、单链表、循环链表和双向链表,我们主要学习单链表。
首先看一下线性顺序表的基本操作List.h
#ifndef LIST_H
#define LIST_H
/************************************************************************/
/* 线性表--顺序表
3 5 7 2 9 1 8
前驱 后继
BOOL InitList(List **list); //创建线性表
void DestroyList(List *list); //销毁线性表
void ClearList(List *list); //清空线性表
BOOL ListEmpty(List *list); //判断线性表是否为空
int ListLength(List *list); //获取线性表长度
BOOL GetElem(List *list,int i,Elem *e); //获取指定元素
int LocateElem(List *list,Elem *e); //寻找第一个满足e的数据元素的位序
BOOL PriorElem(List *list,Elem *currentElem,Elem *preElem); //获取指定元素的前驱
BOOL NextElem(List *list,Elem *currentElem,Elem *nextElem); //获取指定元素的后继
BOOL ListInsert(List *list,int i,Elem *e); //在第i个位置插入元素
BOOL ListDelete(List *list,int i,Elem *e); //在删除第i个位置的元素
void ListTraverse(List *list); //遍历线性表
*/
/************************************************************************/
class List{
public:
List(int size);
~List();
void ClearList();
bool ListEmpty();
int ListLength();
bool GetElem(int i, int *e);
int LocateElem(int *e);
bool PriorElem(int *currentElem, int *preElem);
bool NextElem(int *currentElem, int *nextElem);
void ListTraverse();
bool ListInsert(int i, int *e);
bool ListDelete(int i, int *e);
private:
int *m_pList;
int m_iSize;
int m_iLength;
};
#endif
List的具体实现List.cpp
#include "List.h"
#include
using namespace std;
List::List(int size){
m_iSize = size;
m_pList = new int[m_iSize];
m_iLength = 0;
}
List::~List(){
delete[]m_pList;
m_pList = NULL;
}
void List::ClearList(){
m_iLength = 0;
}
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 i, int *e){
if (i < 0 || i >= m_iSize)
{
return false;
}
*e = m_pList[i];
return true;
}
int List::LocateElem(int *e){
for (int i = 0; i < m_iLength; i++)
{
if (m_pList[i] == *e)
{
return i;
}
}
return -1;
}
bool List::PriorElem(int *currentElem, int *preElem){
int temp = LocateElem(currentElem);
if (temp == -1 || temp == 0)
{
return false;
}
else
{
*preElem = m_pList[temp - 1];
return true;
}
}
bool List::NextElem(int *currentElem, int *nextElem){
int temp = LocateElem(currentElem);
if (temp == -1 || temp == m_iLength - 1)
{
return false;
}
else
{
*nextElem = m_pList[temp + 1];
return true;
}
}
void List::ListTraverse(){
for (int i = 0; i < m_iLength;i++)
{
cout << m_pList[i];
}
}
bool List::ListInsert(int i, int *e){
if (i<0 || i>m_iLength)
{
return false;
}
for (int k = m_iLength - 1; k >= i; k--)
{
m_pList[k + 1] = m_pList[k];
}
m_pList[i] = *e;
m_iLength++;
return true;
}
bool List::ListDelete(int i, int *e){
if (i < 0 || i >= m_iLength)
{
return false;
}
*e = m_pList[i];
for (int k = i + 1; k < m_iLength; k++)
{
m_pList[k-1] = m_pList[k];
}
m_iLength--;
return true;
}
顺序表的优点:在进行遍历和寻址的时候非常快速,效率很高。
缺点:显而易见,当我们想往顺序表中插入一个元素的时候,当前位置向后的所有元素都要向后移动一个位置,这样数据才能顺利地插入进去,删除时同理。那么如何才能避免现象呢?我们需要用到链表。
我们主要学习单链表,单链表 = 顺序表 + 链表节点,主要操作掌握插入、删除节点。
链表节点Node.h
#ifndef NODE_H
#define NODE_H
class Node{
public:
int data; //数据域
Node *next; //指针域
void printNode();
};
#endif
链表节点Node.cpp
#include "Node.h"
#include
using namespace std;
void Node::printNode(){
cout << data << endl;
}
顺序表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);
void ListTraverse();
bool ListInsert(int i, Node *pNode);
bool ListDelete(int i, Node *pNode);
bool ListInsertHead(Node *pNode);
bool ListInsertTail(Node *pNode);
private:
Node *m_pList;
int m_iLength;
};
#endif
顺序表List.cpp
#include "List.h"
#include
using namespace std;
List::List(){
m_pList = new Node;
m_pList->data = 0;
m_pList->next = NULL;
m_iLength = 0;
}
bool List::ListEmpty(){
if (m_iLength == 0)
{
return true;
}
else
{
return false;
}
}
int List::ListLength(){
return m_iLength;
}
void List::ClearList(){
Node *currentNode = m_pList->next;
while (currentNode != NULL)
{
Node *temp = currentNode->next;
delete currentNode;
currentNode = temp;
}
m_pList->next = NULL;
}
List::~List(){
ClearList();
delete m_pList;
m_pList = NULL;
}
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::ListInsertTail(Node *pNode){
Node *currentNode = m_pList;
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
}
Node *newNode = new Node;
if (newNode == NULL)
{
return false;
}
newNode->data = pNode->data;
newNode->next = NULL;
currentNode->next = newNode;
m_iLength++;
return true;
}
bool List::ListInsert(int i, Node *pNode){
if (i <0 || i > m_iLength)
{
return false;
}
Node *currentNode = m_pList;
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;
}
bool List::ListDelete(int i, Node *pNode){
if (i < 0 || i >= m_iLength)
{
return false;
}
Node *currentNode = m_pList;
Node *currentNodeBefore = NULL;
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;
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;
}
bool List::PriorElem(Node *pCurrentNode, Node *pPreNode){
Node *currentNode = m_pList;
Node *tempNode = NULL;
while (currentNode->next != NULL)
{
tempNode = currentNode;
currentNode = currentNode->next;
if (currentNode->data == pCurrentNode->data)
{
pPreNode->data = tempNode->data;
}
}
return false;
}
bool List::NextElem(Node *pCurrentNode, Node *pNextNode){
Node *currentNode = m_pList;
while (currentNode->next != 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();
}
}
测试demo.cpp
#include
#include
#include
#include "List.h"
using namespace std;
int main(void){
Node node1;
node1.data = 3;
Node node2;
node2.data = 4;
Node node3;
node3.data = 5;
Node node4;
node4.data = 6;
Node node5;
node5.data = 7;
Node temp;
List *pList = new List();
/*pList->ListInsertHead(&node1);
pList->ListInsertHead(&node2);
pList->ListInsertHead(&node3);
pList->ListInsertHead(&node4);*/
pList->ListInsertTail(&node1);
pList->ListInsertTail(&node2);
pList->ListInsertTail(&node3);
pList->ListInsertTail(&node4);
pList->ListInsert(1, &node5);
//pList->ListDelete(1, &temp);
//pList->GetElem(1, &temp);
//pList->PriorElem(&node5, &temp);
pList->NextElem(&node5, &temp);
pList->ListTraverse();
cout << "temp=" << temp.data << endl;
delete pList;
pList = NULL;
system("pause");
return 0;
}
测试结果:
通讯录的实现我们可以定义Person类,Person类重载了赋值运算符、比较运算符和输出<<运算符,Person.h
#ifndef PERSON_H
#define PERSON_H
#include
#include
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.cpp
#include "Person.h"
ostream &operator<<(ostream &out, Person &person){
out << person.name << "----" << person.phone << endl;
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;
}