算法与数据结构基础3:简单单链表List类的实现

简单的单链表实现,数据类型定义成了int,如果要通用,需要改成模板类,然后稍微修改下就可以了。

// List.h

#include <cstdio>
#include <cassert>
#include <iostream>

using namespace std;

class List
{
public:
	// **************************************************************************
	// 类的四大函数:构造函数、拷贝构造函数、重载赋值运算符、析构函数
	// **************************************************************************
	List();
	List(const List &list);
	List& operator=(const List &list);
	~List();

	// **************************************************************************
	// 增删改查
	// **************************************************************************
	void PushFront(const int& data);
	int PopFront();
	void PushBack(const int& data);
	int PopBack();

	void reverse();

	unsigned short size();
	bool isEmpty();
	void printList();

private:
	void Free();

private:
	typedef struct Node{
		Node(int d):data(d),next(NULL){}
		int data;
		struct Node* next;
	}Node;

	Node* m_head;
	Node* m_tail;/* 这个变量加得有点鸡肋,最初是想用来操作链表尾,发现只有插入的时候能用,删除的时候用不了,因为没有前指针 */
	unsigned short m_size;
};

// **************************************************************************
// 私有方法
// **************************************************************************
void List::Free()
{
	if(m_head){
		Node* tmp = NULL;
		while(m_head){
			tmp = m_head;
			m_head = m_head->next;
			delete tmp;
		}
	}
	m_head = NULL;
	m_tail = NULL;
	m_size = 0;
}

// **************************************************************************
// 类的四大函数:构造函数、拷贝构造函数、重载赋值运算符、析构函数
// **************************************************************************
List::List()
{
	m_head = NULL;
	m_tail = NULL;
	m_size = 0;
}

List::List(const List &list)
{
	m_head = NULL;
	m_tail = NULL;

	m_size = list.m_size;

	if(list.m_head){
		Node* tmp = list.m_head;
		Node* q = NULL;
		while(tmp){
			Node* node = new Node(tmp->data);
			if(!m_head){
				m_head = node;
				q = m_head;
			}
			else{
				q->next = node;
				q = node;
			}
			tmp = tmp->next;
		}
		m_tail = q;
	}
	else{
		m_head = NULL;
		m_tail = NULL;
	}
}

List& List::operator=(const List &list)
{
	Free();

	m_size = list.m_size;

	if(list.m_head){
		Node* tmp = list.m_head;
		Node* q = NULL;
		while(tmp){
			Node* node = new Node(tmp->data);
			if(!m_head){
				m_head = node;
				q = m_head;
			}
			else{
				q->next = node;
				q = node;
			}

			tmp = tmp->next;
		}
		m_tail = q;
	}
	else{
		m_head = NULL;
		m_tail = NULL;
	}

	return *this;
}

List::~List()
{
	if (m_head){
		Node* tmp = m_head;
		while (tmp){
			m_head = m_head->next;
			delete tmp;
			tmp = m_head;
		}
	}
	m_head = NULL;
	m_tail = NULL;
}

// **************************************************************************
// 增删改查
// **************************************************************************
void List::PushFront(const int& data)
{
	Node* tmp = new Node(data);
	if (!m_head) {
		m_head = tmp;
		m_tail = tmp;
	}
	else{
		tmp->next = m_head;
		m_head = tmp;
	}
	++m_size;
}

int List::PopFront()
{
	assert(m_size > 0);

	Node* tmp = m_head;
	m_head = m_head->next;

	int val = tmp->data;
	delete tmp;
	--m_size;

	return val;
}

void List::PushBack(const int& data)
{
	Node* tmp = new Node(data);
	m_head ? (m_tail->next = tmp) : (m_head = tmp);
	m_tail = tmp;
	++m_size;
}

int List::PopBack()
{
	assert(m_size > 0);

	int val = 0;
	Node *cur, *pri;
	if (!m_head->next){
		val = m_head->data;
		delete m_head;
		m_head = NULL;
		m_tail = NULL;
		m_size = 0;
	}
	else{
		cur = m_head;
		while (cur->next->next){
			cur = cur->next;
		}
		pri = cur;
		m_tail = cur;
		cur = cur->next;
		pri->next = NULL;
		val = cur->data;
		delete cur;
		cur = NULL;

		--m_size;
	}

	return val;
}

void List::reverse()
{
	// 链表为空或只有一个元素,直接返回
	if (!m_head || !m_head->next){
		return;
	}

	Node *pri, *cur, *tmp;
	pri = m_head;
	cur = m_head->next;
	m_head->next = NULL;
	while (cur){
		tmp = cur->next;
		cur->next = pri;
		pri = cur;
		cur = tmp;
	}
	m_head = pri;
}

unsigned short List::size()
{
	return m_size;
}

bool List::isEmpty()
{
	return (m_size == 0);
}

void List::printList()
{
	cout << "size : " << m_size << " , content : ";
	if (m_head){
		Node* tmp = m_head;
		while (tmp){
			cout << tmp->data << " -> ";
			tmp = tmp->next;
		}
	}

	cout << "NULL" << endl;
}

//main.cpp

#include "List.h"
#include <cstdlib>
#include <iostream>
#include <list>

using namespace std;

int main()
{
	List list;
	for (int i = 1; i < 5; ++i){
		list.PushFront(i);
	}
	list.printList();

	list.PushBack(0);
	list.printList();

	List listCopy(list);
	listCopy.printList();

	List listAssig;
	listAssig = list;
	listAssig.printList();

	int popfront = list.PopFront();
	cout << "popfront:" << popfront << endl;
	list.printList();

	int popback = list.PopBack();
	cout << "popback:" << popback << endl;
	list.printList();

	list.reverse();
	cout << "do reverse..." << endl;
	list.printList();

	system("pause");

	return 0;
}

输出截图:

还有些功能没有实现,如在指定位置插入元素,链表搜索等,因为没有迭代器,用index做起来也不是太好,干脆不写算了,日后使用模板,写个通用的。

基于单链表,可以实现队列,堆栈等,稍微扩展下可以实现双链表,以后会把这些一一实现,贴出来。

时间: 2024-10-31 16:33:14

算法与数据结构基础3:简单单链表List类的实现的相关文章

[数据结构]线性表之单链表的类模板实现

类的具体实现如下: ///////////////////////// #include"LinearList.h" #include <iostream> #include <cstdlib> using namespace std; template<class T> struct LinkNode //链表节点类 { T data; LinkNode<T>* link; LinkNode(LinkNode<T>* ptr

算法与数据结构基础10:C++实现——拓扑排序

一 定义 拓扑排序是对有向无环图(Directed Acyclic Graph简称DAG)顶点的一种排序, 它使得如果存在一条从顶点A到顶点B的路径,那么在排序中B出现在A的后面. 二 先决条件 能够进行拓扑排序图有两个先决条件:有向.无环,即有向无环图. 三 偏序全序 连通图:任意两点之间都存在至少一条边 偏序:非连通图(有向无环图满足偏序关系) 全序:单连通图 四 结果唯一性 对于仅满足偏序关系的有向无环图中,因为有两个点之间的关系是不确定的,所以导致排序的结果是不唯一的. 满足全序关系的有

数据结构上机测试2-1:单链表操作A (顺序建表+关键字删除)

数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,将单链表中的值为m的结点全部删除.分别输出建立的初始单链表和完成删除后的单链表. 输入 第一行输入数据个数n: 第二行依次输入n个整数: 第三行输入欲删除数据m. 输出 第一行输出原始单链表的长度: 第二行依次输出原始单链表的数据: 第三行输出完成删除后的单链表长度: 第四行依次输出完成删除后的

数据结构之 线性表---单链表操作A (删除链表中的指定元素)

数据结构上机测试2-1:单链表操作A Time Limit: 1000MS Memory limit: 4096K 题目描述 输入n个整数,先按照数据输入的顺序建立一个带头结点的单链表,再输入一个数据m,将单链表中的值为m的结点全部删除.分别输出建立的初始单链表和完成删除后的单链表. 输入 第一行输入数据个数n: 第二行依次输入n个整数: 第三行输入欲删除数据m. 输出 第一行输出原始单链表的长度: 第二行依次输出原始单链表的数据: 第三行输出完成删除后的单链表长度: 第四行依次输出完成删除后的

算法与数据结构基础11:C++实现——二拆搜索树节点删除

基于我的另一篇文章<算法与数据结构基础4:C++二叉树实现及遍历方法大全> ,二叉树的结构用的这篇文章里的. 二查找叉树的删除可以细分为三种情况: 1 被删除的是叶子节点,直接删除: 2 被删除只有一个子节点,指针下移: 3 有两个子节点,为了不破坏树的结构,需要找出一个节点来替换当前节点. 根据二叉树的特点,当前节点大于所有左子树,小于所有右子树, 可以用左子树中最大的节点,或者右子树最小的节点来替换当前节点,然后删除替换节点. // BSTree.h #include <cstdio

数据结构之 线性表---单链表的操作B(先逆序+再删除重复元素)

数据结构上机测试2-2:单链表操作B Time Limit: 1000MS Memory limit: 65536K 题目描述 按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删除(值相同的元素只保留最后输入的一个). 输入 第一行输入元素个数n: 第二行输入n个整数. 输出 第一行输出初始链表元素个数: 第二行输出按照逆位序所建立的初始链表: 第三行输出删除重复元素后的单链表元素个数: 第四行输出删除重复元素后的单链表. 示例输入 10 21 30 14 55 32 63

算法与数据结构基础 - 广度优先搜索(BFS)

BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数据结构基础 - 队列(Queue) 最直观的BFS应用是图和树的遍历,其中图常用邻接表或矩阵表示,例如 LeetCode题目 690. Employee Importance: // LeetCode 690. Employee Importance/* class Employee { publi

C++ 单链表模板类实现

单链表的C语言描述 基本运算的算法--置空表.求表的长度.取结点.定位运算.插入运算.删除运算.建立不带头结点的单链表(头插入法建表).建立带头结点的单链表(尾插入法建表),输出带头结点的单链表 #include<cstdio>#include<iostream>using namespace std;template <class T>class Linklist{private: struct node { T date; node * next; node():n

算法与数据结构基础7:C++双链表的简单实现

双链表在单链表的基础上加了一个指向前一个节点的指针. // DList.h #include <cstdio> #include <cassert> #include <iostream> using namespace std; class DList { public: // ************************************************************************** // 类的四大函数:构造函数.拷贝构造函数