C++数据结构之单链表

node.h

#ifndef __NODE_H__
#define __NODE_H__

// 结点类模板
template <class ElemType>
struct Node
{
	// 数据成员:
	ElemType data;				// 数据成分
	Node<ElemType>* next;		// 指针成分

// 构造函数模板:
	Node();						// 无参数的构造函数模板
	Node(const ElemType& e, Node<ElemType>* link = NULL);	// 已知数据元素值和指针建立结点
};

// 结点类模板的实现部分
template<class ElemType>
Node<ElemType>::Node()
// 操作结果:构造指针成分为空的结点
{
	next = NULL;
}

template<class ElemType>
Node<ElemType>::Node(const ElemType& e, Node<ElemType>* link)
// 操作结果:构造一个数据成分为e和指针成分为link的结点
{
	data = e;
	next = link;
}

#endif

lk_list.h

#ifndef __LK_LIST_H__
#define __LK_LIST_H__

#include "node.h"									// 结点类模板

// 线性链表类模板
template <class ElemType>
class LinkList
{
protected:
	// 数据成员:
	Node<ElemType>* head;							// 头结点指针
	mutable int curPosition;						// 当前位置的序号
	mutable Node<ElemType>* curPtr;					// 指向当前位置的指针
	int count;										// 元素个数

// 辅助函数模板:
	Node<ElemType>* GetElemPtr(int position) const;	// 返回指向第position个结点的指针

public:
	// 抽象数据类型方法声明及重载编译系统默认方法声明:
	LinkList();										// 无参数的构造函数模板
	virtual ~LinkList();							// 析构函数模板
	int Length() const;								// 求线性表长度			 
	bool Empty() const;								// 判断线性表是否为空
	void Clear();									// 将线性表清空
	void Traverse(void (*visit)(const ElemType&)) const;			// 遍历线性表
	bool GetElem(int position, ElemType& e) const;	// 求指定位置的元素	
	bool SetElem(int position, const ElemType& e);	// 设置指定位置的元素值
	bool Delete(int position, ElemType& e);			// 删除元素		
	bool Delete(int position);						// 删除元素		
	bool Insert(int position, const ElemType& e);	// 插入元素
	LinkList(const LinkList<ElemType>& source);		// 复制构造函数模板
	LinkList<ElemType>& operator =(const LinkList<ElemType>& source); // 重载赋值运算符
};


// 链表类模板的实现部分
template<class ElemType>
Node<ElemType>* LinkList<ElemType>::GetElemPtr(int position) const
// 操作结果:返回指向第position个结点的指针
{
	if (curPosition > position)
	{	// 当前位置在所查找位置之后,只能从表头开始操作
		curPosition = 0;
		curPtr = head;
	}

	for (; curPosition < position; curPosition++)
		curPtr = curPtr->next;						// 查找位置position

	return curPtr;
}

template <class ElemType>
LinkList<ElemType>::LinkList()
// 操作结果:构造一个空链表
{
	head = new Node<ElemType>;						// 构造头结点
	curPtr = head;	curPosition = 0;				// 初始化当前位置
	count = 0;										// 初始化元素个数
}

template <class ElemType>
LinkList<ElemType>::~LinkList()
// 操作结果:销毁线性表
{
	Clear();										// 清空线性表
	delete head;									// 释放头结点所指空间
}

template <class ElemType>
int LinkList<ElemType>::Length() const
// 操作结果:返回线性表元素个数
{
	return count;
}

template <class ElemType>
bool LinkList<ElemType>::Empty() const
// 操作结果:如线性表为空,则返回true,否则返回false
{
	return head->next == NULL;
}

template <class ElemType>
void LinkList<ElemType>::Clear()
// 操作结果:清空线性表
{

	while (!Empty())
	{	// 表性表非空,则删除第1个元素
		Delete(1);									// 删除第1个元素
	}
}

template <class ElemType>
void LinkList<ElemType>::Traverse(void (*visit)(const ElemType&)) const
// 操作结果:依次对线性表的每个元素调用函数(*visit)
{
	for (Node<ElemType>* temPtr = head->next; temPtr != NULL; temPtr = temPtr->next)
	{	// 用temPtr依次指向每个元素
		(*visit)(temPtr->data);						// 对线性表的每个元素调用函数(*visit)
	}
}

template <class ElemType>
bool LinkList<ElemType>::GetElem(int position, ElemType& e) const
// 操作结果:当线性表存在第position个元素时,用e返回其值,返回true,
//	否则返回false
{
	if (position < 1 || position > Length())
	{	// position范围错
		return false;								// 元素不存在
	}
	else
	{	// position合法
		Node<ElemType>* temPtr = GetElemPtr(position);				// 取出指向第position个结点的指针	
		e = temPtr->data;							// 用e返回第position个元素的值
		return true;								// 元素存在
	}
}

template <class ElemType>
bool LinkList<ElemType>::SetElem(int position, const ElemType& e)
// 操作结果:将线性表的第position个位置的元素赋值为e,
//	position的取值范围为1≤position≤Length(),
//	position合法时返回true,否则返回false
{
	if (position < 1 || position > Length())
	{	// position范围错
		return false;								// 范围错
	}
	else
	{	// position合法
		Node<ElemType>* temPtr = GetElemPtr(position);				// 取出指向第position个结点的指针
		temPtr->data = e;							// 设置第position个元素的值
		return true;								// 设置元素成功
	}
}

template <class ElemType>
bool LinkList<ElemType>::Delete(int position, ElemType& e)
// 操作结果:删除线性表的第position个元素, 并用e返回其值,
//	position的取值范围为1≤position≤Length(),
//	position合法时返回true,否则返回false
{
	if (position < 1 || position > Length())
	{	// position范围错
		return false;								// 范围错
	}
	else
	{	// position合法
		Node<ElemType>* temPtr = GetElemPtr(position - 1);			// 取出指向第position-1个结点的指针
		Node<ElemType>* nextPtr = temPtr->next;		// nextPtr为temPtr的后继
		temPtr->next = nextPtr->next;				// 删除结点
		e = nextPtr->data;							// 用e返回被删结点元素值	
		if (position == Length())
		{	// 删除尾结点,当前结点变为头结点
			curPosition = 0;						// 设置当前位置的序号
			curPtr = head;							// 设置指向当前位置的指针
		}
		else
		{	// 删除非尾结点,当前结点变为第position个结点
			curPosition = position;					// 设置当前位置的序号
			curPtr = temPtr->next;					// 设置指向当前位置的指针
		}
		count--;									// 删除成功后元素个数减1 
		delete nextPtr;								// 释放被删结点
		return true;								// 删除成功
	}
}

template <class ElemType>
bool LinkList<ElemType>::Delete(int position)
// 操作结果:删除线性表的第position个元素, 并用e返回其值,
//	position的取值范围为1≤position≤Length(),
//	position合法时返回true,否则返回false
{
	if (position < 1 || position > Length())
	{	// position范围错
		return false;								// 范围错
	}
	else
	{	// position合法
		Node<ElemType>* temPtr = GetElemPtr(position - 1);			// 取出指向第position-1个结点的指针
		Node<ElemType>* nextPtr = temPtr->next;		// nextPtr为temPtr的后继
		temPtr->next = nextPtr->next;				// 删除结点
		if (position == Length())
		{	// 删除尾结点,当前结点变为头结点
			curPosition = 0;						// 设置当前位置的序号
			curPtr = head;							// 设置指向当前位置的指针
		}
		else
		{	// 删除非尾结点,当前结点变为第position个结点
			curPosition = position;					// 设置当前位置的序号
			curPtr = temPtr->next;					// 设置指向当前位置的指针
		}
		count--;									// 删除成功后元素个数减1 
		delete nextPtr;								// 释放被删结点
		return true;								// 删除成功
	}
}


template <class ElemType>
bool LinkList<ElemType>::Insert(int position, const ElemType& e)
// 操作结果:在线性表的第position个元素前插入元素e
//	position的取值范围为1≤position≤Length()+1
//	position合法时返回true, 否则返回false
{
	if (position < 1 || position > Length() + 1)
	{	// position范围错
		return false;								// 范围错
	}
	else
	{	// position合法
		Node<ElemType>* temPtr = GetElemPtr(position - 1);				// 取出指向第position-1个结点的指针
		Node<ElemType>* newPtr = new Node<ElemType>(e, temPtr->next);	// 生成新结点
		temPtr->next = newPtr;						// 将temPtr插入到链表中
		curPosition = position;						// 设置当前位置的序号
		curPtr = newPtr;							// 设置指向当前位置的指针
		count++;									// 插入成功后元素个数加1 
		return true;								// 删除成功
	}
}

template <class ElemType>
LinkList<ElemType>::LinkList(const LinkList<ElemType>& source)
// 操作结果:由线性表source构造新线性表——复制构造函数模板
{
	int sourceLength = source.Length();				// source的长度
	ElemType temElem;								// 临时元素

	// 初始化一个空线性表
	head = new Node<ElemType>;						// 构造头结点
	curPtr = head;	curPosition = 0;				// 初始化当前位置
	count = 0;										// 初始化元素个数

	for (int temPos = 1; temPos <= sourceLength; temPos++)
	{	// 复制数据元素
		source.GetElem(temPos, temElem);			// 取出第temPos个元素
		Insert(Length() + 1, temElem);				// 将temElem插入到当前线性表
	}
}

template <class ElemType>
LinkList<ElemType>& LinkList<ElemType>::operator =(const LinkList<ElemType>& source)
// 操作结果:将线性表source赋值给当前线性表——重载赋值运算符
{
	if (&source != this)
	{
		int sourceLength = source.Length();			// source的长度
		ElemType temElem;							// 临时元素
		Clear();									// 清空当前线性表

		for (int temPos = 1; temPos <= sourceLength; temPos++)
		{	// 复制数据元素
			source.GetElem(temPos, temElem);		// 取出第temPos个元素
			Insert(Length() + 1, temElem);			// 将temElem插入到当前线性表
		}
	}
	return *this;
}

#endif

测试程序

#include <iostream>				// 编译预处理命令
using namespace std;			// 使用命名空间std 
#include "lk_list.h"			// 线性链表类

template <class ElemType>
void Show(const ElemType& e)
// 操作结果: 显示数据元素
{
	cout << e << "  ";
}

int main()
{
	char select = '0';
	LinkList<double> la, lb;
	double e;
	int position;

	while (select != '7')
	{
		cout << endl << "1. 生成线性表.";
		cout << endl << "2. 显示线性表.";
		cout << endl << "3. 检索元素.";
		cout << endl << "4. 设置元素值.";
		cout << endl << "5. 删除元素.";
		cout << endl << "6. 插入元素.";
		cout << endl << "7. 退出";
		cout << endl << "选择功能(1~7):";
		cin >> select;
		switch (select)
		{
		case '1':
			cout << endl << "输入e(e = 0时退出):";
			cin >> e;
			while (e != 0)
			{
				la.Insert(la.Length() + 1, e);
				cin >> e;
			}
			break;
		case '2':
			lb = la;
			lb.Traverse(Show<double>);
			break;
		case '3':
			cout << endl << "输入元素位置:";
			cin >> position;
			if (!la.GetElem(position, e))
				cout << "元素不存储." << endl;
			else
				cout << "元素:" << e << endl;
			break;
		case '4':
			cout << endl << "输入位置:";
			cin >> position;
			cout << endl << "输入元素值:";
			cin >> e;
			if (!la.SetElem(position, e))
				cout << "位置范围错." << endl;
			else
				cout << "设置成功." << endl;
			break;
		case '5':
			cout << endl << "输入位置:";
			cin >> position;
			if (!la.Delete(position, e) && !la.Delete(position))
				cout << "位置范围错." << endl;
			else
				cout << "被删除元素值:" << e << endl;
			break;
		case '6':
			cout << endl << "输入位置:";
			cin >> position;
			cout << endl << "输入元素值:";
			cin >> e;
			if (!la.Insert(position, e))
				cout << "位置范围错." << endl;
			else
				cout << "成功:" << e << endl;
			break;
		}
	}

	return 0;					// 返回值0, 返回操作系统
}

例程均来自清华大学出版社 《数据结构与算法》(C++版)作者:唐宁九 游洪跃。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值