单项链表
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,链表比较方便插入和删除操作。
创建头节点
手动new一个新的Node,将Node的next置为NULL即可。
head = new Node(0);head->next = NULL;
从头插入一个新的节点
手动new出一个新的节点p,使p的next的指向head->next所指向的地址,然后将head->next从新指向p即可。
Node * p = new Node(int); p->next = head->next; head->next = p;
删除指定节点
先遍历到指定节点的前一个节点,然后通过将前一个节点的next指针指向指定节点的下一个节点,达到悬空指定节点的效果,然后删除指定节点即可。代码请参照后面的完整代码。
修改指定节点
遍历到指定节点的位置,将其data修改为要修改的值即可。修改代码请参考后面的完整代码。
链表反转
定义三个临时节点指向头结点之后的第1个节点p,第2个节点q和第3个节点m。将p->next置为空,然后将q->next = p,然后将p向后移动一个节点,即p = q,最后将q向后移动一个节点,即q = m,最后把m向后移动一个节点,即m = m->next;依此类推直到m等于NULL,然后将q->next = p,最后将head->next指向q(即目前第一个节点疑,也就是原本最后的一个节点)。
通过三个节点达到从头开始逐个逆序的目的。反转代码请参考后面的完整代码。
// SingleLinkedListNode.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
//
// SingleLinedListNode.cpp
// 单项链表
// Created by huyanfeng 2019.03.19
//
#include <iostream>
using namespace std;
class SingleLinedListNode
{
public:
SingleLinedListNode() { CreateSingleLinedListNode(); }
~SingleLinedListNode() { Clear(); }
private:
//节点结构
struct NodeInfo
{
int nData;
NodeInfo * pNext;
NodeInfo(const int& nData) :nData(nData), pNext(NULL) {}
};
//清理链表函数
void Clear()
{
//从头节点开始循环删除
while (m_pHead)
{
NodeInfo * pNext = m_pHead->pNext;
delete m_pHead;
m_pHead = pNext;
}
}
//查找数据d的上一个节点位置的函数
//为了方便后面删除操作
NodeInfo* find(const int& nData)
{
NodeInfo * pNode = m_pHead;
for (; pNode != NULL; pNode = pNode->pNext)
{
if (pNode->pNext->nData == nData)
break;
}
return pNode;
}
public:
//创建头结点
void CreateSingleLinedListNode();
//插入函数
void InsertNode(const int& nData);
//在指定位置插入
void InsertPos(const int& nData1, const int& nData2);
//删除指定数据的节点
void RemoveNode(const int& nData);
//修改指定数据
void UpdateNode(const int& nData1, const int& nData2);
//反转链表函数
void ReverseNode();
//打印
void Print();
private:
NodeInfo * m_pHead;//头节点
};
//创建头结点
void SingleLinedListNode::CreateSingleLinedListNode()
{
m_pHead = new NodeInfo(0);
}
//从头插入一个节点
void SingleLinedListNode::InsertNode(const int& nData)
{
NodeInfo *pNewNode = new NodeInfo(nData);
pNewNode->pNext = m_pHead->pNext;
m_pHead->pNext = pNewNode;
}
//打印函数
void SingleLinedListNode::Print()
{
for (NodeInfo * pNode = m_pHead->pNext; pNode; pNode = pNode->pNext) {
cout << pNode->nData << endl;
}
}
//在nNode1位置之后插入nNode2
void SingleLinedListNode::InsertPos(const int& nData1, const int& nData2)
{
NodeInfo * pNode = find(nData1);
NodeInfo * qNode = new NodeInfo(nData2);
qNode->pNext = pNode->pNext;
pNode->pNext = qNode;
}
//删除
void SingleLinedListNode::RemoveNode(const int& nData)
{
NodeInfo * pNode = find(nData);
//因为p是上一个节点的位置,用q来保存
//要删除的节点的地址
NodeInfo *qNode = pNode->pNext;
//通过将上一个节点的next指针指向要删除节点的next指
//针志向的节点实现断开要删除节点的目的
pNode->pNext = pNode->pNext->pNext;
//删除要删除的节点q
delete qNode;
}
//修改指定数据
void SingleLinedListNode::UpdateNode(const int& nData1, const int& nData2)
{
NodeInfo * pNode = find(nData1);
pNode->pNext->nData = nData2;
}
//反转链表
void SingleLinedListNode::ReverseNode()
{
NodeInfo * pNode = m_pHead->pNext;//头结点之后的第1个节点
NodeInfo * qNode = m_pHead->pNext->pNext;//头结点之后的第2节点
NodeInfo * mNode = m_pHead->pNext->pNext->pNext;//头结点之后的第3个节点
pNode->pNext = NULL;//将头接点之后的第1个节点的next指针置为空
//根据m是否为空来判断 以此逆序每一个节点
while (mNode)
{
qNode->pNext = pNode;
pNode = qNode;
qNode = mNode;
mNode = mNode->pNext;
}
//将最后一个节点逆序
qNode->pNext = pNode;
//将头从新指向新的的第1个节点(之前的最后一个节点)
m_pHead->pNext = qNode;
}
int main(int argc, const char * argv[])
{
// insert code here...
SingleLinedListNode list;
list.InsertNode(1);
list.InsertNode(2);
list.InsertNode(3);
list.InsertPos(2, 5);
list.Print();
cout << "---------------------" << endl;
list.RemoveNode(1);
list.Print();
cout << "---------------------" << endl;
list.ReverseNode();
list.Print();
cout << "---------------------" << endl;
list.UpdateNode(5, 4);
list.Print();
return 0;
}
结果: