C++实现单链表(2)
单链表操作之结点删除,结点插入,链表翻转
前面一节实现了链表的基本操作,本节实现链表常用操作,虽然很常用,实现起来却比较复杂。
1、结点删除
删除结点可以按照位置删除,也可以按照数据删除,这里实现的是按照位置删除。在删除之前,取需要判断删除位置是否合法,以及删除的位置是否会大于链表的总长度。
template<typename Datatype>
inline void LinkList<Datatype>::Delete(int delete_location)
{
if (0 >= delete_location || this->Length() <= delete_location)
throw "删除位置错误";
int count = 1;
Node<Datatype>* p = this->first;
while (count < delete_location)
{
count++;
p = p->next;
}
/**
* 当p为待插入位置的上一个元素时,退出循环
*/
Node<Datatype>* q = p->next;
p->next = q->next;
//释放空间,删除干净
delete q;
}
这里了的遍历需要遍历到删除位置元素的前一个元素,因为遍历到删除元素无法向前遍历,除非是双向链表或者创建一个变量来存储前一个结点的指针,这里完全没有必要。同时删除元素也要将对应结点的空间释放掉,防止内存泄漏。
2、结点插入
结点插入同样需要遍历到插入位置的前一个结点,同时允许插入位置大于链表总长度+1,实现尾插。同时插入结点是要申请堆区内存空间用来存储需要插入的结构体。
template<typename Datatype>
inline void LinkList<Datatype>::Insert(const Datatype& insert_data, int insert_location)
{
if (0 >= insert_location || this->Length() + 1 < insert_location)
throw "插入位置错误";
int count = 1;
Node<Datatype>* p = this->first;
while (count < insert_location)
{
count++;
p = p->next;
}
/**
* 当p为待插入位置的上一个元素时,退出循环
* 初始化待插入结点
* 将节点用头插的方式插入链表中
*/
Node<Datatype>* s = new Node<Datatype>;
s->Data = insert_data;
s->next = p->next;
p->next = s;
}
3、链表翻转
链表翻转使用以下方法:
1-判断链表长度是否大于1,如果大于1,则进行第2步,否则,退出函数。
2-堆区开辟内存申请一个结点大小的内存空间,将其作为新链表头结点,初始化。
3-从头遍历原链表每个元素并依次将元素插入到新链表的头结点之后,释放原链表每个结点内存。
4-将原链表头指针指向新链表头结点。
template<typename Datatype>
inline void LinkList<Datatype>::Reverse()
{
int length = this->Length();
if (0 == length || 1 == length) return;
Node<Datatype>* p = this->first, * p_next = p->next;
//如果链表长度小于等于1,初始化新链表头结点
Node<Datatype> *p_tar = new Node<Datatype>;
p_tar->next = nullptr;
for (int i = 0; i < length; i++)
{
//为待插入新链表的结点分配空间
Node<Datatype> *s = new Node<Datatype>;
//待插入结点填入数据
Datatype data = p_next->Data;
s->Data = data;
//新节点头插方式插入新链表
s->next = p_tar->next;
p_tar->next = s;
//释放旧结点空间
delete p;
//p和p_next指针后移
p = p_next;
p_next = p_next->next;
}
//将新头结点指针赋值给first
this->first = p_tar;
}
4、测试代码
#include <iostream>
#include <string>
#include "LinkList.hpp"
using namespace std;
int main()
{
string string_array[] = { " This ", " is ", " string_list ", " test." };
//使用带参构造数据域为string类型的链表
LinkList<string>* list_string_p = new LinkList<string>
(string_array, sizeof(string_array) / sizeof(string_array[0]));
try
{
cout << "链表带参构造后遍历:";
list_string_p->PrintList();
cout << "string链表第4个元素:" << list_string_p->Get(4) << endl;
list_string_p->Insert(" a ", 3);
cout << "在第三个位置插入a:";
list_string_p->PrintList();
list_string_p->Delete(3);
cout << "删除第三个元素后:";
list_string_p->PrintList();
list_string_p->Reverse();
cout << "链表翻转:";
list_string_p->PrintList();
//list_string_p->Empty();
cout << "链表长度:" << list_string_p->Length() << endl;
}
catch (const char* catch_string)
{
cout << catch_string << endl;
}
delete list_string_p;
system("pause");
return 0;
}
5、测试结果
6、 总结
异常的测试也通过,这里不再演示。
新人才疏学浅,有错的地方敬请指正!!
本文来自博客园,作者:夏末终年,转载请注明出处:https://www.cnblogs.com/xiamozhongnian/p/15890390.html