🟦首先我们先来个概念了解(什么是单向链表)
单向链表属于链表中的一类,链表是用于数据元素的线性集合,其中每个元素都指向下一个元素,元素存储上并不连续。单向链表的特性是每个元素只知道其下一个元素是谁。
🟦单向链表实现的几个功能汇总
1️⃣创建两个类,一个类是节点类,一个类中实现单向链表的功能
class Node//节点类
{
friend class SinglyLinkedList;
//由于我们把m_Value和m_Next属性设置成私有属性,类外无法访问到,使用友元让我们指定的类可以访问
public:
Node(int value, Node* next)//构造函数,给属性赋初值
{
this->m_Value = value;
this->m_Next = next;
}
private:
int m_Value;//值
Node* m_Next;//下一个节点指针
};
class SinglyLinkedList//单向链表的内部实现
{
public:
SinglyLinkedList()//构造函数,给属性赋初值
{
m_Head = NULL;
}
//功能函数的声明
//为了提高程序的可读性,我们在类外实现功能函数
private:
Node* m_Head;//头指针
};
有可能一些小可爱们🤗不知道头指针的含义,下面👇是关于头指针的解释
2️⃣实现从链表头部添加的功能void addFirst(int value)
----->思路分析
将头指针m_Head指向新加进来的节点,新加进来的节点m_Next指针指向原先头指针指向的节点
👇下面就是代码呈现
void SinglyLinkedList::addFirst(int value)
{
//1.链表为空的情况
//m_Head = new Node(value, NULL);
//2.链表不为空的情况
m_Head = new Node(value, m_Head);//链表为空或非空的情况都适用
}
3️⃣实现链表遍历的功能void Loop1() 或void Loop2() (这里提供两种遍历方法)
用while循环实现遍历
void SinglyLinkedList::Loop1()//用while实现遍历链表
{
Node* p = m_Head;
while (p != NULL)
{
cout << p->m_Value <<' ';
p = p->m_Next;
}
}
用for循环实现链表遍历
void SinglyLinkedList::Loop2()//用for循环实现遍历链表
{
for (Node* p = m_Head; p != NULL; p = p->m_Next)
{
cout << p->m_Value << ' ';
}
}
4️⃣实现从链表尾部添加的功能void addFirst(int value)
思路分析🎇:要从链表尾部添加,首先就要找到最后一个节点,我们可以遍历链表,然后返回最后一个节点,所以我们可以把找最后一个节点封装成一个函数 Node* findLast();
代码呈现
Node* SinglyLinkedList::findLast()
{
if (m_Head == NULL)//空链表
{
return NULL;
}
Node* p;
for (p = m_Head; p->m_Next != NULL; p=p->m_Next) { ; }
return p;
}
void SinglyLinkedList::addLast(int value)
{
Node* pl = findLast();
if (pl == NULL)
{
addFirst(value);
}
else
{
pl->m_Next= new Node(value, NULL);
}
}
5️⃣实现根据索引返回节点的值的功能int get(int index)
思路分析🎇:首先我们需要找到节点,遍历链表找索引,当i等于我们想要找的索引index时,返回节点
Node* SinglyLinkedList::findNode(int index)
{
int i = 0;
Node* p;
for (p = m_Head; p != NULL; p = p->m_Next,i++)
{
if (i == index)
{
return p;
}
}
return NULL;//没找到
}
再通过get函数找到索引所指向的值
int SinglyLinkedList::get(int index)
{
Node* node = findNode(index);
if (node == NULL)
{
cout << "很遗憾,没有找到" << endl;
system("pause");
exit(0);
}
return node->m_Value;
}
❌但是这里存在一个小问题,就是当findNode返回为空的时候不能用exit(0),因为用它是退出整个程序,也就是说在测试时其后面的测试案例都执行不了,但是博主现在能力有限还无法解决这个问题,各位大佬们,有解决方法可以在评论中留言🫶❤️
6️⃣实现向索引位置插入的功能void insert(int index,int value)
思路分析🎇:要向索引为index的位置添加节点,就要找到索引为index-1的节点,让其的m_Next指针指向要添加的节点,要添加的节点的m_Next指针指向原先索引为index的节点
void SinglyLinkedList::insert(int index,int value)
{
if (index == 0)
{
addFirst(value);
return;
}
Node* prev = findNode(index - 1);//找到上一个节点
if (prev == NULL)
{
cout << "index的输入超出链表范围" << endl;
return;
}
prev->m_Next = new Node(value, prev->m_Next);
}
//前面提供了findNode函数这里就不展示了
7️⃣实现删除第一个节点的功能void removeFirs()
思路分析🎇:头指针m_Head指向m_Head->m_Next
void SinglyLinkedList::removeFirst()
{
if (m_Head == NULL)
{
cout << "链表为空,无法删除第一个节点" << endl;
return;
}
Node* tmp = m_Head;
m_Head = m_Head->m_Next;
//为了防止内存泄露,要手动释放删除的第一个节点
delete tmp;
}
8️⃣实现根据索引删除节点void remove(int index)
思路分析🎇:用findNode函数找到索引为index-1的节点,让其m_Next指向索引为index的m_Next
void SinglyLinkedList::remove(int index)
{
if (index == 0)
{
removeFirst();
return;
}
Node* prev = findNode(index - 1);
if (prev == NULL)
{
cout << "索引输入有误,超出单向链表范围" << endl;
return;
}
Node* remove = prev->m_Next;//被删除的节点
if (remove == NULL)
{
cout << "无法删除" << endl;
return;
}
prev->m_Next = remove->m_Next;
}
🎉🎉🎉关于单链表的功能就已经全部实现了,将其功能都封装在SinglyLinkedList这个类中
class SinglyLinkedList//单向链表的内部实现
{
public:
SinglyLinkedList()//构造函数,给属性赋初值
{
m_Head = NULL;
}
void addFirst(int value);//从链表头部添加
void Loop1();//遍历链表
void Loop2();//遍历链表
void addLast(int value);//从链表尾部添加
int get(int index);//根据索引返回对象的值
void insert(int index,int value);//向索引位置插入
void removeFirst();//删除第一个节点
void remove(int index);//根据索引删除节点
private:
Node* findLast();//找最后一个节点
Node* findNode(int index);//给索引返回节点对象
private:
Node* m_Head;//头指针
};
这篇blog到这里就已经结束了🎉🎉🎉,创作不易,还望各位多多支持,想要点赞,关注,收藏❤️🫶😘🥰🥳