[朝花夕拾]单链表篇-C++

朝花夕拾

  • [朝花夕拾]单链表篇-C++
    • 单链表结构定义-
      • 头文件 singly_list.h
    • 测试数据结构定义
      • 头文件 student.h
      • 源文件 student.cpp
    • 简单的测试函数编写-main函数

[朝花夕拾]单链表篇-C++

本例结合模板对单链表进行了一个简单的C++实现,可为数据结构新手进行学习提供参考,中间可能有考虑不周之处烦请指出,该文章属于作者原创文章,当前时间节点前全网没有第二篇,转载请注明出处,支持个人劳动成果。

单链表结构定义-

头文件 singly_list.h

#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);
	}
}

测试数据结构定义

头文件 student.h

#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";
};

源文件 student.cpp

#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");
}

简单的测试函数编写-main函数

#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;
}

你可能感兴趣的:(数据结构)