接上文:https://blog.csdn.net/weixin_43217963/article/details/88723766
3.链表
3.1单链表
链式存储:用一组任意的存储单元存储线性表中的数据元素(可以使连续的,也可以是不连续的),数据元素之间的逻辑关系借助指示元素存储位置的指针来表示。
链表的每个节点由两部分组成:数据域data和指针域*next。
- 数据域用来存放该节点的数据元素本身的信息;指针域用来指向下一个结点的存储位置。
线性链表的特点:
- 结点在存储器的位置是任意的,节点之间的逻辑关系由结点中的指针来指示。
- H是指针变量,该变量保存着指向单链表的第一个结点的指针,称为头指针。(头结点中数据域不存放信息,指针域即为头指针)对单链表中任一结点的访问必须从头指针开始。最后一个结点的指针指向NULL。
3.2其他链表
链表又分为单链表、循环链表、双向链表、双向循环链表。
循环链表:循环链表是一种首尾相接的链表。在单链表中,如果最后一个结点的指针域的值不是NULL而是指向头结点,则为循环链表。
- 其特点是从表中任意结点出发均可找到表中其他的结点
- 单循环链表与单链表操作基本一致,但需要将算法中的循环条件p->next是否为空改为是否等于头指针。
双向链表:在单链表的基础上,再加上一个指向前驱的指针域,这样,链表的每一个结点中有一个数据域data,两个指针域(一个指向直接前驱prior,一个指向直接后继next),则为双向链表。
- 显然,双向链表中找每一个结点的前驱后继都很方便
双向循环链表:和单循环链表一样,将双向链表的头结点和尾结点链接起来,就形成了双向循环链表。
- 双向循环链表是将头结点的前驱指针指向了尾结点,同时尾结点的后继指针指向了头结点。
- 空的双向循环链表中,头结点的前驱和后继指针均指向了自己,这是其判空条件。
3.3单链表代码示例:
c语言的定义实现:
typedef int elemtype;
typedef struct node
{
elemtype data;//数据域
struct node *next;指针域
}Lnode;
c++实现单链表
node.h
#ifndef NODE_H
#define NODE_H
#include<iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
void printInfo()
{
cout << data << endl;
}
};
#endif
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);//获取第i个结点
int LocateElem(Node *pNode); //获取第一个满足e的结点的位序
//bool PriorElem(Node *pCrrentNode, Node *pPreNode);//找出给定结点的前驱
//bool NextElem(Node *pCrrentNode, Node *pNextNode);//找出给定结点的后继
bool ListInsert(int i, Node *pNode);//第i个位序插入结点
bool ListDelete(int i, Node *pNode);//删除第i个位序的结点
void ListTraverse();//遍历
bool ListInsertHead(Node *pNode);//在第一个结点之前插入元素
bool ListInsertTail(Node *pNode);//在最后一个结点后插入元素
private:
Node *m_pList;
int m_iLen;
};
#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_iLen = 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;
delete currentNode;
currentNode = temp;
}
m_pList->next = NULL;
}
bool List::ListEmpty()
{
return m_iLen == 0 ? true : false;
}
int List::ListLength()
{
return m_iLen;
}
bool List::ListInsert(int i, Node *pNode)
{
if (i<0 || i>m_iLen)
return false;
Node *currentNode = m_pList;
for (int j = 0; j < i; j++)//找到第i-1个位序结点
{
currentNode = currentNode->next;
}
Node *newNode = new Node;
if (newNode == NULL)
return false;
newNode->data = pNode->data;
newNode->next = currentNode->next;
currentNode->next = newNode;
return true;
}
bool List::ListDelete(int i, Node *pNode)
{
if (i<0 || i>=m_iLen)
return false;
Node *currentNode = m_pList;
for (int j = 0; j < i; j++)//找到第i-1个位序结点
{
currentNode = currentNode->next;
}
Node *temp = currentNode->next;
pNode->data = temp->data;
currentNode->next = temp->next;
delete temp;
m_iLen--;
return true;
}
bool List::GetElem(int i, Node *pNode)
{
if (i < 0 || i >= m_iLen)
return false;
Node *preNode = m_pList;
for (int j = 0; j < i - 1; j++)//找到第i-1个结点
{
preNode = preNode->next;
}
pNode->data = preNode->next->data;
return true;
}
int List::LocateElem(Node *pNode)
{
Node *currentNode = m_pList;
int count = 1;
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
if (currentNode->data == pNode->data)
{
return count;
}
count++;
}
return -1;
}
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_iLen++;
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;
currentNode->next = newNode;
newNode->next = NULL;
m_iLen++;
return true;
}
void List::ListTraverse()
{
Node *currentNode = m_pList;
while (currentNode->next != NULL)
{
currentNode = currentNode->next;
currentNode->printInfo();
}
}
main.cpp
#include<iostream>
#include"list.h"
#include"node.h"
int main(void)
{
//测试
/*Node node1;
node1.data = 3;
Node node2;
node2.data = 4;
Node node3;
node3.data = 5;
Node node4;
node4.data = 10;
Node node5;
List *pList = new List;
pList->ListInsertHead(&node1);
pList->ListInsertHead(&node2);
pList->ListInsertHead(&node3);
pList->ListInsert(2, &node4);
pList->ListDelete(2, &node5);
pList->ListTraverse();*/
system("pause");
return 0;
}