48 c++模板库数据结构

该博客详细介绍了如何使用C++模板类实现线性表的顺序存储(SeqList)和链式存储(LinkList),包括增删查改等基本操作。此外,还展示了如何利用链式存储实现栈(LinkStack)的数据结构,支持压栈、弹栈、查看栈顶元素和检查栈的大小。示例代码中涉及了结构体 Teacher 的使用,以及动态内存管理和深拷贝问题。
摘要由CSDN通过智能技术生成

1 线性表顺序存储

SeqList.h

#pragma once
template <typename T>
class SeqList
{
public:
	SeqList(int capacity);
	~SeqList();

	// 返回一个线性表list中的元素个数
	int get_Length();

	int get_Capacity();

	// 向一个线性表list的pos位置中插入新元素node
	int insert(T &t, int pos);

	// 获取一个线性表list的pos位置处的元素
	int get(T &list, int pos);

	// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
	int del(T& list, int pos);
    
    // 清空链表
    int clear();

private:
	int length;
	int capacity;
	T* pArray;		// 数组
};

SeqList.cpp

#include "SeqList.h"
#include<iostream>

template <typename T>
SeqList<T>::SeqList(int capacity)
{
	// T* pArray;	// 数组
	pArray = new T[capacity];
	this->capacity = capacity;
	this->length = 0;
}

template <typename T>
SeqList<T>::~SeqList()
{
	delete[]pArray;
	pArray = NULL;
	length = 0;
	capacity = 0;
}


// 返回一个线性表list中的元素个数
template <typename T>
int SeqList<T>::get_Length() {
	return this->length;
}

template <typename T>
int SeqList<T>::get_Capacity() {
	return capacity;
}

// 向一个线性表list的pos位置中插入新元素node
template <typename T>
int SeqList<T>::insert(T& t, int pos) {
	int i = 0;
	if (pos < 0) {
		return -1;
	}

	// 元素后移
	for (i = this->length; i > pos; i--) {
		pArray[i] = pArray[i-1];
	}

	pArray[i] = t;	//stl元素保存是通过复制的机制实现的,类需要可以复制
	this->length++;
	return 0;
}

// 获取一个线性表list的pos位置处的元素
template <typename T>
int SeqList<T>::get(T& t, int pos) {
	int i = 0;
	if (pos < 0) {
		return -1;
	}
	t = pArray[pos];
	return 0;
}

// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
template <typename T>
int SeqList<T>::del(T& t, int pos) {
	int i = 0;
	t = pArray[pos];
	for (i = pos + 1; i < length; i++) {
		pArray[i - 1] = pArray[i];
	}
	this->length--;
	return 0;
}

template<typename T>
int SeqList<T>::clear(){
    this->length = 0;
	return 0;
}

mainseqlist.cpp

#include<iostream>

// 模板需要加cpp
#include"SeqList.cpp"
using namespace std;


struct Teacher
{
	char name[64];
	int age;
};
void main_seqlist_play() {
	Teacher t1, t2, t3, tmp;
	t1.age = 21;
	t2.age = 22;
	t3.age = 23;
	SeqList<Teacher> list(10);
	list.insert(t1, 0);
	list.insert(t2, 0);
	list.insert(t3, 0);

	// 测试链表遍历
	for (int i = 0; i < list.get_Length(); i++) {
		list.get(tmp, i);
		cout << tmp.age << " "; 
	}
	cout << endl;
    
    list.clear();

	list.insert(t1, 0);
	list.insert(t2, 0);
	list.insert(t3, 0);
    
	while (list.get_Length() > 0) {
		list.del(tmp, 0);
		cout << tmp.age << " ";
	}
	cout << endl;
}

void main_seqlist_play02() {
	Teacher t1, t2, t3;
	Teacher* p1, * p2, * p3;
	Teacher* tmp;
	t1.age = 21;
	t2.age = 22;
	t3.age = 23;

	p1 = &t1;
	p2 = &t2;
	p3 = &t3;
	
	
	SeqList<Teacher *> list(10);
	list.insert(p1, 0);
	list.insert(p2, 0);
	list.insert(p3, 0);

	// 测试链表遍历
	for (int i = 0; i < list.get_Length(); i++) {
		list.get(tmp, i);
		cout << tmp->age << " ";
	}
	cout << endl;
	while (list.get_Length() > 0) {
		list.del(tmp, 0);
		cout << tmp->age << " ";
	}
	cout << endl;
}

void main() {
	main_seqlist_play();
	main_seqlist_play02();
}

结果

23 22 21
23 22 21
23 22 21
23 22 21

2 线性表链式存储

LinkList.h

#pragma once

// 在插入元素时,模板类中应该把每一个t保存下来
// 模板类中应该能分配节点缓存节点

// 怎么样缓存==>linklist 链表
template<typename T>
struct Node {
	T t;
	Node* next;
};

template <typename T>
class LinkList
{
public:
	LinkList();
	~LinkList();

	// 返回一个线性表list中的元素个数
	int get_Length();

	int get_Capacity();

	// 向一个线性表list的pos位置中插入新元素node
	int insert(T& t, int pos);

	// 获取一个线性表list的pos位置处的元素
	int get(T& list, int pos);

	// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
	int del(T& list, int pos);

	int clear();

private:
	Node<T>* head;	// 在链表中需要建一个带有头节点的链表
	int length;
};

LinkList.cpp

#include "LinkList.h"
#include<iostream>


template<typename T>
LinkList<T>::LinkList()
{
	head = new Node<T>;
	head->next = NULL;
	length = 0;
}

template<typename T>
LinkList<T>::~LinkList()
{
	Node<T>* tmp = NULL;
	while (head != NULL) {
		tmp = head->next;		// 删除链表的时候缓存后面节点
		delete head;
		head = tmp;
	}
	length = 0;
	head = NULL;
}


// 返回一个线性表list中的元素个数
template<typename T>
int LinkList<T>::get_Length() {
	return length;
}

// 向一个线性表list的pos位置中插入新元素node
template<typename T>
int LinkList<T>::insert(T& t, int pos) {
	Node<T>* current = NULL;
	current = head;
	
	for (int i = 0; i < pos; i++) {
		current = current->next;
	}
	
	// 思考 node 节点存在吗? 不存在 需要申请
	Node<T>* node = new Node<T>;
	if (node == NULL) {
		return -1;
	}
	node->t = t;	// 缓存外部数据
	node->next = NULL;
	// 新节点连接后续链表
	node->next = current->next;
	// 连接新节点
	current->next = node;

	length++;

	return 0;
}

// 获取一个线性表list的pos位置处的元素
template<typename T>
int LinkList<T>::get(T& t, int pos) {
	Node<T>* current = NULL;
	current = head;

	for (int i = 0; i < pos; i++) {
		current = current->next;
	}

	t = current->next->t;	// 把缓存的t传给调用者

	return 0;
}

// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
template<typename T>
int LinkList<T>::del(T& t, int pos) {
	Node<T>* current = NULL;
	Node<T>* ret = NULL;
	current = head;

	for (int i = 0; i < pos; i++) {
		current = current->next;
	}
	ret = current->next;	// 被删除元素

	t = ret->t;		// 把缓存数据拷贝出
	current->next = ret->next;
	length--;
	
	delete ret;

	return 0;

}

template<typename T>
int LinkList<T>::clear() {
	Node<T>* tmp = NULL;
	while (head != NULL) {
		tmp = head->next;		// 删除链表的时候缓存后面节点
		delete head;
		head = tmp;
	}
	length = 0;
	head = NULL;

	head = new Node<T>;
	head->next = NULL;
	length = 0;
	return 0;
}

main

#include<iostream>

// 模板需要加cpp
#include"SeqList.cpp"
#include"LinkList.cpp"
using namespace std;


struct Teacher
{
	char name[64];
	int age;
};
void main_linklist_play() {
	Teacher t1, t2, t3, tmp;
	t1.age = 21;
	t2.age = 22;
	t3.age = 23;
	LinkList<Teacher> list;
	list.insert(t1, 0);
	list.insert(t2, 0);
	list.insert(t3, 0);

	// 测试链表遍历
	for (int i = 0; i < list.get_Length(); i++) {
		list.get(tmp, i);
		cout << tmp.age << " ";
	}
	cout << endl;

	list.clear();

	list.insert(t1, 0);
	list.insert(t2, 0);
	list.insert(t3, 0);

	// 销毁链表
	while (list.get_Length() > 0) {
		list.del(tmp, 0);
		cout << tmp.age << " ";
	}
	cout << endl;
}

void main() {
	main_linklist_play();
}

加入指针之后,需要考虑拷贝复制中的问题

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>

// 模板需要加cpp
#include"SeqList.cpp"
#include"LinkList.cpp"
using namespace std;


struct Teacher
{
public:
	char name[64];
	int age;
	char* pdes;
	Teacher(){
		memset(name, 0, sizeof(name));
		age = 0;
		pdes = NULL;
	}
	Teacher(const Teacher& obj) {
		pdes = (char*)malloc(100);
		strcpy(this->pdes, obj.pdes);
		strcpy(this->name, obj.name);
		age = obj.age;
	}
	~Teacher() {
		if (pdes != NULL) {
			free(pdes);
		}
	}
	// t1 = t2;
	Teacher& operator=(const Teacher& obj) {
		// 清除t1内存空间
		if (pdes != NULL && pdes != obj.pdes) {
			free(pdes);
			pdes = NULL;
			pdes = (char*)malloc(100);
			strcpy(this->pdes, obj.pdes);
		}
		strcpy(this->name, obj.name);
		age = obj.age;
		return *this;
	}
};

void main_linklist_play() {
	Teacher t1, t2, t3, tmp;
	t1.age = 21;
	t2.age = 22;
	t3.age = 23;

	t1.pdes = (char *)malloc(100);
	strcpy(t1.pdes, "t1t1t1");

	t2.pdes = (char*)malloc(100);
	strcpy(t1.pdes, "t2t2t2");

	t3.pdes = (char*)malloc(100);
	strcpy(t1.pdes, "t3t3t3");

	LinkList<Teacher> list;
	list.insert(t1, 0);
	list.insert(t2, 0);
	list.insert(t3, 0);

	// 测试链表遍历
	for (int i = 0; i < list.get_Length(); i++) {
		list.get(tmp, i);
		cout << tmp.age << " ";
	}
	cout << endl;

	list.clear();

	list.insert(t1, 0);
	list.insert(t2, 0);
	list.insert(t3, 0);

	// 销毁链表
	while (list.get_Length() > 0) {
		list.del(tmp, 0);
		cout << tmp.age << " ";
	}
	cout << endl;
}

void main() {
	main_linklist_play();

}

3 栈(利用线性表链式存储实现)

LinkStack.h

#pragma once
#include"LinkList.h"
template<typename T>
class LinkStack
{
public:
	LinkStack();
	~LinkStack();

	void clear();

	int push(T& t);

	int pop(T& t);

	int top(T& t);
	
	int size();
private:
	LinkList<T>* list;
};

LinkStack.cpp

#include "LinkStack.h"
#include<iostream>

template<typename T>
LinkStack<T>::LinkStack()
{
	// 创建栈 相当于创建线性表
	list = new LinkList<T>;
}

template<typename T>
LinkStack<T>::~LinkStack()
{
	clear();
	delete list;
	list = NULL;
}

template<typename T>
void LinkStack<T>::clear() {
	// 清空一个栈 相当于 清空一个链表
	list->clear();
}

template<typename T>
int LinkStack<T>::push(T& t) {
	// 向栈中添加元素相当于在 链表的头部添加元素
	return list->insert(t, 0);
}

template<typename T>
int LinkStack<T>::pop(T& t) {
	// 从栈中添加元素相当于从 线性表头部删除元素
	return list->del(t, 0);
}

template<typename T>
int LinkStack<T>::top(T& t) {
	// 从栈顶获取元素 相当于从线性表中获取0号位置
	return list->get(t, 0);
}

template<typename T>
int LinkStack<T>::size() {
	return list->get_Length();
}

main.cpp

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>

// 模板需要加cpp
#include"LinkStack.cpp"
using namespace std;


struct Teacher
{
public:
	char name[64];
	int age;
}

void main_linkstack_play() {

	// 创建栈 
	LinkStack<Teacher> stack;
	Teacher t1, t2, t3;
	Teacher tmp;
	t1.age = 21;
	t2.age = 22;
	t3.age = 23;
	stack.push(t1);
	stack.push(t2);
	stack.push(t3);

	// 获取栈顶元素
	stack.top(tmp);
	cout << tmp.age << endl;

	cout << stack.size() << endl;
	// 栈的删除
	while (stack.size() > 0) {
		stack.pop(tmp);
		cout << tmp.age << " ";
	}


}

void main() {

	main_linkstack_play();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值