单链表模板类c++实现

1、题目描述

实现课本中的带附加头结点的单链表模板类,完成如下功能:
定义链表节点的结构体类型,构造函数和析构函数,单链表的输入输出
引用型操作:getData,Locate ,Search,Length,IsEmpty, getHead
加工型操作:setData,Insert,Remove
在main方法中以一串整数为例测试以上所有的操作。

2、设计思路

/* Search */
查找x的位置,返回指向x的指针
初始化当前指针current为first
通过current对链表中所有指针遍历
判断current所指向的data是否与x相等
相等返回current,否则返回NULL

/* Insert */
将新元素插入在链表中第i个结点之后
判断输入是否合法
首先定位第i个结点
新生成一个数据域为x的结点
让其指向第i+1个结点的后一个结点
令定位的当前节点current指向新结点
链表长度加1

/* Remove */
将链表中第i个元素删除,通过引用型参数返回该元素的值
定位第i-1个结点
初始化一个新结点del,指向被删除的结点
定位的第i-1个结点的指针域指向被删除结点的后一个结点
将del结点的数据域赋值给引用型参数x
释放del结点,链表长度-1

LinkList.h文件如下:

#include<iostream>
using namespace std;
template <class T>  //结点结构定义
struct LinkNode {
	T data;                         //结点数据 
	LinkNode<T>* link;    //结点链接指针
	LinkNode(LinkNode<T>* ptr = NULL) { link = ptr; }  //构造函数	
	LinkNode(const T& item, LinkNode<T>* ptr = NULL) { data = item; link = ptr; }
};
template<class T>
class List {
protected:
	struct LinkNode<T>* first;
public:
	List() { first = new LinkNode<T>; }         //构造函数
	List(const T& x) { first = new LinkNode<T>(x); }      //构造函数
	List(List<T>& L);             //复制构造函数
	~List() { makeEmpty(); }            //析构函数
	void makeEmpty();             //将链表置空
	int Length() const;             //计算链表的长度
	LinkNode<T>* getHead() const { return first; }
	LinkNode<T>* Search(T x);           //搜素数据为x的节点
	LinkNode<T>* Locate(int i)const;          //搜索第i个元素的地址
	bool getData(int i, T& x) const;         //取出第i个节点的数据
	void setData(int i, T& x);           //用x修改第i个元素的值
	bool Insert(int i, T& x);           //在第i个节点后插入新节点
	bool Remove(int i, T& x);           //删除第i个节点数据返回到x中
	bool IsEmpty() const            //判断表是否为NULL
	{
		return first->link == NULL ? true : false;
	}
	bool IsFull() const { return false; }        //判断表满
	void Sort();              //排序
	void InputFront(T  endFlag);          //倒序创建单链表
	void InputRear(T endFlag);           //正序创建单链表
	void Output();              //输出
	List<T>& operator=(List<T>& L);         //重载赋值运算符
};

List.cpp文件如下:

#include"linkedlist.h"
#include<iostream>
using namespace std;
template<class T>
List<T>::List(List<T>& L) {
	//复制构造函数
	T value;
	LinkNode<T>* srcptr = L.getHead();
	LinkNode<T>* destptr = first = new LinkNode<T>;
	while (srcptr->link != NULL) {          //逐一赋值
		value = srcptr->link->data;
		destptr->link = new LinkNode<T>(value);
		destptr = destptr->link;          //左值游动指针移动到下一个
		srcptr = srcptr->link;           //右值游动指针移动到下一个
	}
	destptr->link = NULL;
}
template<class T>
void List<T>::makeEmpty() {
	LinkNode<T> *q;
	while(first->link!=NULL){
		q=first->link;
		first->link=q->link;
		delete q;
	}
}
template<class T>
int List<T>::Length() const {
	//计算带附加头节点的单链表的长度
	LinkNode<T>* p = first->link;
	int count = 0;
	while (p != NULL) {
		count++;
		p = p->link;
	}
	return count;
}
template<class T>
LinkNode<T>* List<T>::Search(T x) {
	//在表中搜索含数据x的节点,搜索成功时返回该节点的地址,否则返回NULL
	LinkNode<T>* current = first->link;
	while (current != NULL) {
		if (current->data == x) break;
		else current=current->link;
	}
	return current;
}
template<class T>
LinkNode<T>* List<T>::Locate(int i)const{
	//定位函数 返回表中第i个节点的地址 如果i < 0 或者i 超过链表长度则返回NULL
	if (i < 0) return NULL;
	LinkNode<T>* current = first;
	int m = 0;
	while (current != NULL && m < i) {
		current = current->link;
		m++;
	}
	return current;
}
template<class T>
bool List<T>::getData(int i, T& x) const {
	//取出链表中第i个节点的data
	if (i <= 0) return NULL;             //数据非法返回false
	LinkNode<T>* current = Locate(i);         //借助定位函数直接定位到相应的节点
	if (current == NULL) return false;             //i超过单链表的长度返回false
	else {
		x = current->data;
		return true;
	}
}
template<class T>
void List<T>::setData(int i, T& x) {
	//设置链表的第i个元素为x
	if (i <= 0) return;
	LinkNode<T>* current = Locate(i);
	if (current == NULL) return;
	else current->data = x;
}
template<class T>
bool List<T>::Insert(int i, T& x) {
	//在i个节点之后插入新节点
	LinkNode<T>* current = Locate(i);
	if (NULL == current) return false;
	LinkNode<T>* newNode = new LinkNode<T>(x);
	if (NULL == newNode) 
		cout << "存储分配错误" << endl;
	newNode->link = current->link;
	current->link = newNode;
	return true;
}
template<class T>
bool List<T>::Remove(int i, T& x) {
	//将链表中第i个节点删除 删除成功返回true并将删除的data存储在x中
	LinkNode<T>* current = Locate(i - 1);        //定位到指向i节点的节点
	if (NULL == current || NULL == current->link) return false;             //不存在待删除的节点
	LinkNode<T>* del = current->link;         //标记待删除的节点
	current->link = del->link;           //重新拉链
	x = del->data;              //记录下删除节点的data
	delete del;               //释放删除节点
	return true;
}
template<class T>
void List<T>::Output(){
	//单链表的输出函数 :将单链表中所有节点的data按逻辑顺序输出到屏幕上
	LinkNode<T>* current = first->link;        //创建遍历指针
	while (current != NULL) {
		cout<<current->data << ' ';
		current=current->link;
	}
	cout<<endl;
}
template<class T>
void List<T>::InputRear(T endFlag) {
	//函数功能 : 顺序建立单链表
	//函数参数 : 输入结束标志的数据
	LinkNode<T>* newNode, *last;          //需要一个指针时刻标记结尾
	T val;
	makeEmpty();
	cin >> val;
	last = first;              //首先令last指针指向头节点
	while (val != endFlag) {
		newNode = new LinkNode<T>(val);
		if (newNode== NULL) 
			cout << "内存分配错误" << endl;
		last->link = newNode;
		last = newNode;
		cin >> val;
	}
	last->link = NULL;
}
int main()
{
	List<int> x; 
	List<int> y; 
	List<int> z;
	LinkNode <int>*p,*q,*r;
	cout<<"请输入第一个链表(结束符为0):";
	x.InputRear(0);//以0作为结束符正序创建链表
	cout<<"请输入第二个链表(结束符为0):";
	y.InputRear(0);
	p = x.getHead();
	q = y.getHead();
	r = z.getHead();   //新链表 
	q = q->link; 
	p = p->link;
	cout << "归并前的链表一:" << endl;
	x.Output();
	cout << "归并前的链表二:" << endl;
	y.Output();
	while(p&&q)
	{
		if(p->data <= q->data)
		{
			r->link=p;
			r = p;
			p = p->link;
			continue;
		}
		if(p->data>q->data)
		{
			r->link=q;
			r = q;
			q = q->link;
			continue;
		}
	}
	if(p)
	{
		while(p)
		{
			r->link = p;
			r = p;
			p = p->link;
		}
	}
	if(q)
	{
		while(q)
		{
			r->link = q;
			r = q;
			q = q->link;
		}
	}
	cout<<"归并后的链表为:"<<endl;
	z.Output();
}
  • 1
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值