线性表-单链表

本文档展示了如何使用C++实现单链表数据结构,包括`SingleLinkList.h`头文件和`SingleLinkListTest.cpp`测试文件。在Visual Studio 2015环境下进行了测试并得到了成功运行的结果。
摘要由CSDN通过智能技术生成

SingleLinkList.h

#pragma once

template <class DataType>
struct Node
{
	DataType data;
	Node<DataType> *next;
};

//注:头结点不作为数据结点使用,其存储的first->data是单链表的长度,因此单链表的长度是不计算头结点的。

template <class DataType>
class SingleLinkList
{
public:
	SingleLinkList();//无参数构造函数
	SingleLinkList(DataType a[], int n);//有参数构造函数:用含n个元素的数组采用前插法初始化单链表【始终将新建结点插入在头结点和第一个结点之间】
	SingleLinkList(int n, DataType a[]);//有参数构造函数:用含n个元素的数组采用尾接法初始化单链表【始终将新建结点插入作为单链表的最后一个结点】【建议使用该法】
	~SingleLinkList();//析构函数
	int GetLength();//获得单链表长度
	bool IsEmpty();//判断单链表是否为空
	DataType GetValueByLocation(int i);//按位查找返回单链表的第i个元素
	DataType DeleteByLocation(int i);//删除单链表的第i个元素并返回删除的值
	DataType DeleteAtHead();//删除头部元素并返回删除的值
	DataType DeleteAtTail();//删除尾部元素并返回删除的值
	DataType GetMaxElement();//获得单链表的最大元素
	DataType GetMinElement();//获得单链表的最小元素
	Node<DataType> *GetFirst();//获得单链表的头指针
	void MergeIncrementally(SingleLinkList<DataType>* LA, SingleLinkList<DataType>* LB, SingleLinkList<DataType>* LC);//递增地合并单链表LA和LB到LC
	void Insert(int i, DataType x);//按位插入元素
	void InsertAtHead(DataType x);//在头部插入元素
	void InsertAtTail(DataType x);//在尾部插入元素
	void PrintSingleLinkList();//遍历单链表
	void ClearSingleLinkList();//清空单链表
	void ReverseSingleLinkList();//倒置【反转】单链表
	void SetValueAtLocation_iBy_x(int i, DataType x);//设置位置i的元素的值为x
	void SortSingleLinkList();//把单链表从小到大排序
private:
	Node<DataType> *first;
};

template<class DataType>
inline SingleLinkList<DataType>::SingleLinkList()
{
	first = new Node<DataType>;
	first->next = NULL;
	first->data = 0;
}

template<class DataType>
inline SingleLinkList<DataType>::SingleLinkList(DataType a[], int n)//每次把新建结点作为第一结点
{
	first = new Node<DataType>;
	Node<DataType> *s;
	first->next = NULL;
	for (int i = 0; i < n; i++) {
		s = new Node<DataType>;
		s->data = a[i];
		s->next = first->next;
		first->next = s;
	}
	first->data = n;
}

template<class DataType>
inline SingleLinkList<DataType>::SingleLinkList(int n, DataType a[])//每次把新建结点作为最后结点
{
	first = new Node<DataType>;
	first->next = NULL;
	Node<DataType> *temp = first;//temp作为尾指针
	Node<DataType> *s;
	for (int i = 0; i < n; i++) {
		s = new Node<DataType>;
		s->data = a[i];
		temp->next = s;
		temp = s;
	}
	temp->next = NULL;
	first->data = n;
}

template<class DataType>
inline SingleLinkList<DataType>::~SingleLinkList()
{
	Node<DataType> *p = first;
	while (p) {
		Node<DataType> *q = p;
		p = p->next;
		delete q;
	}
}

template<class DataType>
inline int SingleLinkList<DataType>::GetLength()
{
	return first->data;
}

template<class DataType>
inline bool SingleLinkList<DataType>::IsEmpty()
{
	if (first->data == 0 || first->next == NULL)
		return true;
	else return false;
}

template<class DataType>
inline DataType SingleLinkList<DataType>::GetValueByLocation(int i)
{
	if (i > first->data || IsEmpty()) {
		cout << "delete error!" << endl;
		return -1;
	}
	Node<DataType> *p = first->next;
	for (int j = 1; j < i; p = p->next) {
		j++;
	}
	return p->data;
}

template<class DataType>
inline DataType SingleLinkList<DataType>::DeleteByLocation(int i)
{
	if (i > first->data || IsEmpty()) {
		cout << "delete error!" << endl;
		return -1;
	}
	int j = 1;
	Node<DataType> *q = first;
	Node<DataType> *p = first->next;
	while (j < i)
	{
		q = p;
		p = p->next;
		j++;
	}
	q->next = p->next;
	DataType temp = p->data;
	first->data--;
	delete p;
	return temp;
}

template<class DataType>
inline DataType SingleLinkList<DataType>::DeleteAtHead()
{
	if (IsEmpty()) {
		return -1;
	}
	Node<DataType> *p = first->next;
	first->next = p->next;
	DataType temp = p->data;
	first->data--;
	delete p;
	return temp;
}

template<class DataType>
inline DataType SingleLinkList<DataType>::DeleteAtTail()
{
	if (IsEmpty()) {
		return -1;
	}
	Node<DataType> *p = first;
	Node<DataType> *q = first->next;
	while (q->next)
	{
		p = q;
		q = q->next;
	}
	p->next = NULL;
	DataType temp = q->data;
	first->data--;
	delete q;
	return temp;
}

template<class DataType>
inline DataType SingleLinkList<DataType>::GetMaxElement()
{
	if (IsEmpty()) {
		cout << "get error!" << endl;
		return -1;
	}
	Node<DataType> *p = first->next;
	DataType max = p->data;
	for (p = p->next; p != NULL; p = p->next) {
		if (p->data > max) {
			max = p->data;
		}
	}
	return max;
}

template<class DataType>
inline DataType SingleLinkList<DataType>::GetMinElement()
{
	if (IsEmpty()) {
		cout << "get error!" << endl;
		return -1;
	}
	Node<DataType> *p = first->next;
	DataType min = p->data;
	for (p = p->next; p != NULL;p = p->next) {
		if (p->data < min) {
			min = p->data;
		}
	}
	return min;
}

template<class DataType>
inline Node<DataType>* SingleLinkList<DataType>::GetFirst()
{
	if (first->data == 0 || IsEmpty()) {
		cout << "get error!" << endl;
		return nullptr;
	}
	return first;
}

template<class DataType>
inline void SingleLinkList<DataType>::MergeIncrementally(SingleLinkList<DataType> *LA, SingleLinkList<DataType> *LB, SingleLinkList<DataType> *LC)
{
	LA->SortSingleLinkList();//首先使得LA,LB变成递增有序.
	LB->SortSingleLinkList();
	Node<DataType> *pa, *pb, *s, *r;
	int count = 0;
	pa = LA->first->next;
	pb = LB->first->next;
	r = LC->first;//r当前作为LC的头结点
	while (pa && pb)
	{
		if (pa->data <= pb->data)
		{
			s = new Node<DataType>;
			s->data = pa->data;
			r->next = s;
			pa = pa->next;
			r = s;
			count++;
		}
		else
		{
			s = new Node<DataType>;
			s->data = pb->data;
			r->next = s;
			pb = pb->next;
			r = s;
			count++;
		}
	}
	while (pa)
	{
		s = new Node<DataType>;
		s->data = pa->data;
		r->next = s;
		pa = pa->next;
		r = s;
		count++;
	}
	while (pb)
	{
		s = new Node<DataType>;
		s->data = pb->data;
		r->next = s;
		pb = pb->next;
		r = s;
		count++;
	}
	r->next = NULL;
	LC->first->data = count;
}

template<class DataType>
inline void SingleLinkList<DataType>::Insert(int i, DataType x)
{
	if (i > first->data+1 ) {
		cout << "insert error!" << endl;
		return;
	}
	int j = 1;
	Node<DataType> *q = first;
	Node<DataType> *p = first->next;
	while (j < i)
	{
		q = p;
		p = p->next;
		j++;
	}
	Node<DataType> *temp = new Node<DataType>;
	temp->data = x;
	q->next = temp;
	temp->next = p;
	first->data++;
}

template<class DataType>
inline void SingleLinkList<DataType>::InsertAtHead(DataType x)
{
	Node<DataType> *temp = new Node<DataType>;
	temp->data = x;
	temp->next = first->next;
	first->next = temp;
	first->data++;
}

template<class DataType>
inline void SingleLinkList<DataType>::InsertAtTail(DataType x)
{
	Node<DataType> *q = first->next;
	while (q->next)
	{
		q = q->next;
	}
	Node<DataType> *temp = new Node<DataType>;
	q->next = temp;
	temp->next = NULL;
	temp->data = x;
	first->data++;
}

template<class DataType>
inline void SingleLinkList<DataType>::PrintSingleLinkList()
{
	if (first->data == 0 || IsEmpty()) {
		cout << "print error!" << endl;
		return;
	}
	int j=0;
	Node<DataType> *q = first->next;
	while (q)
	{
		cout << q->data << " ";
		q = q->next;
		j++;
		if (j % 50 == 0)
			cout << endl;
	}
	cout << endl;
}

template<class DataType>
inline void SingleLinkList<DataType>::ClearSingleLinkList()
{
	Node<DataType> *p;
	Node<DataType> *q = first->next;
	while (q)
	{
		p = q;
		q = q->next;
		delete p;
	}
	first->next = NULL;
	first->data = 0;
}

template<class DataType>
inline void SingleLinkList<DataType>::ReverseSingleLinkList()
{
	if (IsEmpty())
		return;
	Node<DataType> *previos, *current, *back;
	current = first->next;
	back = current->next;
	while (back)
	{
		previos = current;
		current = back;
		back = back->next;
		current->next = previos;
	}
	first->next->next = NULL;
	first->next = current;
}

template<class DataType>
inline void SingleLinkList<DataType>::SetValueAtLocation_iBy_x(int i, DataType x)
{
	if (i > first->data || IsEmpty()) {
		cout << "set error!" << endl;
		return;
	}
	int j = 1;
	Node<DataType> *p = first->next;
	while (j < i)
	{
		p = p->next;
		j++;
	}
	p->data = x;
}

template<class DataType>
inline void SingleLinkList<DataType>::SortSingleLinkList()
{
	if (IsEmpty()) {
		cout << "sort error!" << endl;
		return;
	}
	int i;
	int N = first->data;
	DataType *arr = new DataType[N];
	Node<DataType> *p = first->next;
	for (i=0; p != NULL; p = p->next,i++) {//先把所有结点的数据提取到一个数组arr中存储
		arr[i] = p->data;
	}
	DataType temp;
	for (i = 1; i < N; i++) {	//选用插入排序对数组arr从小到大排序
		for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
			temp = arr[j];
			arr[j] = arr[j - 1];
			arr[j - 1] = temp;
		}
	}
	for (i = 0,p=first->next; p != NULL; p = p->next, i++) {//为每个结点从小到大赋值
		p->data = arr[i];
	}
	delete[] arr;
}

SingleLinkListTest.cpp

测试平台: Visual Studio 2015

#include<iostream>
#include"SingleLinkList.h" //若把此两个的头文件顺序互换,会出现何种情况?
using namespace std;
void main()
{
	int a[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 };
	int b[] = { -9,6,88,-7,-91,52,33,20,15,-44 };
	SingleLinkList<int> Test1(a, sizeof(a) / sizeof(a[0]));//前插法初始化单链表
	cout << "打印前插法初始化的单链表:";
	Test1.PrintSingleLinkList();
	cout << "       获得单链表1的长度:" << Test1.GetLength() << endl;
	
	SingleLinkList<int> Test2(sizeof(b) / sizeof(b[0]),b);//尾接法初始化单链表
	cout << "打印尾接法初始化的单链表:";
	Test2.PrintSingleLinkList();
	cout << "       获得单链表2的长度:" << Test2.GetLength() << endl;

	cout << "     获得单链表2的最大值:" << Test2.GetMaxElement() << endl;
	cout << "     获得单链表2的最小值:" << Test2.GetMinElement() << endl;

	cout << "     单链表2删除头部元素:" << Test2.DeleteAtHead() << endl;
	cout << "     单链表2删除尾部元素:" << Test2.DeleteAtTail() << endl;
	cout << "             打印单链表2:";
	Test2.PrintSingleLinkList();
	cout << "       获得单链表2的长度:" << Test2.GetLength() << endl;

	cout << "单链表2位置为4的元素的值:" << Test2.GetValueByLocation(4) << endl;
	cout << "单链表2删除位置为7的元素:" << Test2.DeleteByLocation(7) << endl;
	cout << "             打印单链表2:";
	Test2.PrintSingleLinkList();
	cout << "       获得单链表2的长度:" << Test2.GetLength() << endl;

	cout << " 单链表2在头部插入元素33:" << endl;
	Test2.InsertAtHead(33);
	cout << " 单链表2在尾部插入元素-3:" << endl;
	Test2.InsertAtTail(-3);

	cout << "             打印单链表2:";
	Test2.PrintSingleLinkList();
	cout << "       获得单链表2的长度:" << Test2.GetLength() << endl;

	cout << "设置单链表2中位置为5的元素为333:" << endl;
	Test2.SetValueAtLocation_iBy_x(5, 333);
	cout << "     倒置【反转】单链表2:" << endl;
	Test2.ReverseSingleLinkList();
	cout << "             打印单链表2:";
	Test2.PrintSingleLinkList();
	cout << "       获得单链表2的长度:" << Test2.GetLength() << endl;

	cout << "             单链表2排序:" << endl;
	Test2.SortSingleLinkList();
	cout << "             打印单链表2:";
	Test2.PrintSingleLinkList();


	cout << "     获得单链表1的最大值:" << Test1.GetMaxElement() << endl;
	cout << "     获得单链表1的最小值:" << Test1.GetMinElement() << endl;

	cout << "     单链表1删除头部元素:" << Test1.DeleteAtHead() << endl;
	cout << "     单链表1删除尾部元素:" << Test1.DeleteAtTail() << endl;
	cout << "             打印单链表1:";
	Test1.PrintSingleLinkList();
	cout << "      获得单链表1的长度:" << Test1.GetLength() << endl;

	cout << "单链表1位置为6的元素的值:" << Test1.GetValueByLocation(6) << endl;
	cout << "单链表1删除位置为8的元素:" << Test1.DeleteByLocation(8) << endl;
	cout << "             打印单链表2:";
	Test1.PrintSingleLinkList();
	cout << "       获得单链表1的长度:" << Test1.GetLength() << endl;

	cout << " 单链表1在头部插入元素11:" << endl;
	Test1.InsertAtHead(11);
	cout << " 单链表1在尾部插入元素-1:" << endl;
	Test1.InsertAtTail(-1);

	cout << "             打印单链表1:";
	Test1.PrintSingleLinkList();
	cout << "       获得单链表1的长度:" << Test1.GetLength() << endl;

	cout << "设置单链表1中位置为15的元素为888:" << endl;
	Test1.SetValueAtLocation_iBy_x(15, 888);
	cout << "     倒置【反转】单链表1:" << endl;
	Test1.ReverseSingleLinkList();
	cout << "             打印单链表1:";
	Test1.PrintSingleLinkList();
	cout << "       获得单链表1的长度:" << Test1.GetLength() << endl;

	cout << "             单链表1排序:" << endl;
	Test1.SortSingleLinkList();
	cout << "             打印单链表1:";
	Test1.PrintSingleLinkList();
	
	cout << "             打印单链表2:"; 
	Test2.PrintSingleLinkList();
	cout << "合并单链表1和2到单链表LC:" << endl;
	SingleLinkList<int> LC;
	LC.MergeIncrementally(&Test1, &Test2, &LC);
	cout << "            打印单链表LC:";
	LC.PrintSingleLinkList();
	cout << "      获得单链表LC的长度:" << LC.GetLength() << endl;

	cout << "   判断单链表1是否为空表:" << Test1.IsEmpty() << endl;
	cout << "             清空单链表1:" << endl;
	Test1.ClearSingleLinkList();
	cout << "   判断单链表1是否为空表:" << Test1.IsEmpty() << endl;

	cout << "单链表1删除位置为5的元素:";
	Test1.DeleteByLocation(5);
}

运行结果

在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值