本例结合模板对单链表进行了一个简单的C++实现,可为数据结构新手进行学习提供参考,中间可能有考虑不周之处烦请指出,该文章属于作者原创文章,当前时间节点前全网没有第二篇,转载请注明出处,支持个人劳动成果。
#ifndef SIGNLY_LIST
#define SIGNLY_LIST
#include
using namespace std;
template
class Node {
public:
Node(const T& _data, Node* _next = NULL)
{
data = _data; // 数据结构T若不对=进行重载就会发生浅拷贝现象,导致内存错误
next = _next;
}
public:
T data;
Node* next;
};
template
class SinglyList {
private:
Node* header; // 头节点指针
int m_size; // 链表长度
private:
bool isInvalidPos(int pos);
public:
SinglyList();
~SinglyList();
bool isEmpty()const;
int size();
void add(const Node& _node,int pos);
void addToTail(const Node& _node);
void remove(int pos);
void update(const Node& _node,int pos);
Node getNode(int pos);
void printList();
};
#endif
template
inline bool SinglyList::isInvalidPos(int pos)
{
return (pos<0 || pos>=m_size)?true:false;
}
// 初始化单链表
template
inline SinglyList::SinglyList()
{
header = NULL;
m_size = 0;
}
// 析构函数,释放单链表空间
template
inline SinglyList::~SinglyList()
{
if (m_size > 0) {
// destroy memory
Node* ptr = header;
while (header->next != NULL) {
header = header->next;
ptr->next = NULL;
delete ptr;
ptr = header;
}
}
}
// 判断单链表是否为空或长度是否为零
template
inline bool SinglyList::isEmpty() const
{
return m_size==0 || header==NULL;
}
// 返回单链表长度
template
inline int SinglyList::size()
{
return m_size;
}
// 在单链表某个位置增加一个节点
template
inline void SinglyList::add(const Node& _node, int pos)
{
if (isInvalidPos(pos)) {
cout << "pos invalid!\n";
return;
}
else {
Node* prev = header;
Node* ptr=header;
for (int i = 0; i < pos; i++) {
ptr=ptr->next;
if (i == pos - 1)
continue;
prev=prev->next;// 保证在pos的前一个节点
}
// 当前ptr指针指向位置为pos处的节点
// 设置新节点的next指向该pos处的节点的起始位置
Node* node = new Node(_node.data,ptr);
prev->next = node;// prev指针指向刚才新添加入的节点的起始地址
m_size++;
}
}
// 在单链表的末尾增加一个节点
template
inline void SinglyList::addToTail(const Node& _node)
{
if (m_size == 0) {
header = new Node(_node.data, NULL);
m_size++;
}
else if(m_size>0){
Node* prev = header;
Node* ptr = header;
while (ptr) {
ptr=ptr->next;
if (ptr == NULL) {
cout << "end while.\n";
break;
}
prev = ptr;
}
if (prev != NULL) {
prev->next = new Node(_node.data, NULL);
}
m_size++;
}
}
// 移除单链表中某个位置的节点
template
inline void SinglyList::remove(int pos)
{
if (isInvalidPos(pos)) {
cout << " invalid pos! \n";
return;
}
else {
if (pos > 0) {
Node* prev = header;
Node* ptr = header;
for (int i = 0; i < pos; i++) {
ptr = ptr->next;
if (i == pos - 1)
continue;
prev = prev->next;
}
prev->next = ptr->next;
ptr->next = NULL;
delete ptr; // 释放掉这块内存,不知道是否存在问题,如果这块内存不是从堆区申请的,那咋办嘞
ptr = NULL;
}
else if(pos==0){
Node* ptr = header;
header = header->next;
ptr->next = NULL;
delete ptr;
ptr = NULL;
}
}
}
// 对单链表中某个位置的节点进行更新
template
inline void SinglyList::update(const Node& node, int pos)
{
if (isInvalidPos(pos)) {
cout << "invalid pos!\n";
return;
}
else {
Node* ptr = header;
for (int i = 0; i < pos; i++) {
ptr=ptr->next;
}
ptr->data = node.data;
}
}
// 得到单链表中某个位置的节点数据
template
inline Node SinglyList::getNode(int pos)
{
if (isInvalidPos(pos)) {
cout << "invalid pos!\n";
return Node(T());
}
else {
Node* ptr = header;
for (int i = 0; i < pos; i++) {
ptr=ptr->next;
}
Node node = Node(ptr->data, ptr->next);
return node;
}
}
template
inline void SinglyList::printList()
{
if (m_size <= 0) {
cout << "There is no data in list...\n";
return;
}
else {
Node* ptr = header;
do {
// 要求T数据进行<<流操作符的重载,所以说这个函数定义在SinglyList应该是不妥当的,暂且先这样处理
cout << ptr->data;
ptr = ptr->next;
} while (ptr!=NULL);
}
}
#pragma once
#include
#include
using namespace std;
class Student {
public:
Student();
Student(long id, string name);
~Student();
friend ostream& operator<<(ostream& os,const Student& _student);
private:
long m_id=-1L;
string m_name="invalid name";
};
#include "student.h"
Student::Student()
{
}
Student::Student(long id, string name)
{
m_id = id;
m_name = name;
}
Student::~Student()
{
}
ostream& operator<<(ostream& os, const Student& _student)
{
// TODO: 在此处插入 return 语句
return (os<<"[ " << _student.m_id << ", "<<_student.m_name<<" ]\n");
}
#include "singly_list.h"
#include "student.h"
#include
using namespace std;
int main() {
SinglyList list;
// 测试addToTail函数
list.addToTail(Student(1L, "鸣人"));
list.addToTail(Student(2L,"佐助"));
list.addToTail(Student(3L, "旗木卡卡西"));
// 测试size函数
cout << "当前单链表的长度为: " << list.size() << "\n";
// 输出当前链表信息
list.printList();
cout << "\n";
// 测试add函数
list.add(Student(4L, "斑"),2);
// 输出当前链表信息
cout << "当前单链表的长度为: " << list.size() << "\n";
list.printList();
// 待测函数
cout << "测试 isEmpty函数...\n";
cout << (list.isEmpty() ? "是" : "否") << "\n";
cout << "测试remove函数...\n";
list.remove(0);
list.printList();
list.addToTail(Student(7L, "红凯"));
list.printList();
// 测试update函数
cout << "测试update函数...\n";
Node node(Student(101L,"我爱罗"));
list.update(node, 3);
list.printList();
// 越界测试
cout << "测试update函数(越界测试)...\n";
list.update(node, 10);
list.printList();
cout << "测试getNode函数(正常位置)...\n";
Node stu1=list.getNode(2);
cout << stu1.data;
cout << "测试getNode函数(越界测试)...\n";
Node stu2 = list.getNode(10);
cout << stu2.data;
return 0;
}