以C++实现的数据结构与算法(链表)


链表

带头结点和不带头结点的区别:

  • 1、不带头结点的单链表对于第一个节点的操作与其他节点不一样,需要特殊处理,这增加了程序的复杂性和出现bug的机会,因此,通常在单链表的开始结点之前附设一个头结点。

  • 2、带头结点的单链表,初始时一定返回的是指向头结点的地址,所以一定要用二维指针,否则将导致内存访问失败或异常。

  • 3、带头结点与不带头结点初始化、插入、删除、输出操作都不样,在遍历输出链表数据时,带头结点的判断条件是while(head->next!=NULL),而不带头结点是while(head!=NULL),虽然头指针可以在初始时设定,但是如1所述,对于特殊情况如只有一个节点会出现问题。


linkList.h头文件,可直接调用使用

#pragma once
#include<iostream>
using namespace std;

//链表结点
template<class T>
class LinkNode {
	template<class T>
	friend class LinkList;
public:
	LinkNode() {
		next = NULL;
	}
private:
	T data;//数据
	LinkNode<T>*next;//指向下一个节点的指针
};
//链表
template<class T>
class LinkList {
public:
	LinkList();//构造函数
	~LinkList();//析构函数
	LinkList<T>&insert(int index, const T&x);//插入
	bool isEmpty()const;
	int getLength()const;
	T getData(int index);
	bool modifyData(int index, const T&x);
	int find(const T&x);
	LinkList<T>&deleteByIndex(int index);
	LinkList<T>&deleteByKey(const T&x);
	void outPut(ostream&cout);
private:
	LinkNode<T>*head;//头结点
};
//插入
template<class T>
LinkList<T>&LinkList<T>::insert(int index, const T&x) {
	LinkNode<T>*p = head;
	LinkNode<T>*newNode = new LinkNode<T>();
	newNode->data = x;
	if (index < 1 || index>this->getLength() + 1) {
		cout << "插入元素下标越界,插入失败!!!" << endl;
	}
	else {
		for (int i = 1; i < index; i++)
		{
			p = p->next;
		}
		newNode->next = p->next;
		p->next = newNode;
	}
	return *this;
}
//按位置删除
template<class T>
LinkList<T>&LinkList<T>::deleteByIndex(int index) {
	if (index>=1&&index<=this->getLength()) {
		LinkNode<T>*p = head;
		LinkNode<T>*q = NULL;
		for (int i = 1; i < index; i++)
		{
			p = p->next;
		}
		q = p->next;
		p->next = q->next;
		delete q;
	}
	else {
		cout << "删除元素下标越界,删除失败!!!(index)" << endl;
	}
	return *this;
}
//删除
template<class T>
LinkList<T>&LinkList<T>::deleteByKey(const T&x) {
	int index = this->find(x);
	if (index) {
		this->deleteByIndex(index);
	}
	else {
		cout << "删除元素找不到,删除失败!!!(key)" << endl;
		return *this;
	}
}
//判断是否空表
template<class	T>
bool LinkList<T>::isEmpty()const {
	return this->head->next == NULL;
}
//构造
template<class T>
LinkList<T>::LinkList() {
	head = new LinkNode<T>();
}
//析构
template<class	T>
LinkList<T>::~LinkList() {
	for (int i = this->getLength(); i >1; i--)
	{
		this->deleteByIndex(i);
	}
	delete head;
}
//长度
template<class T>
int LinkList<T>::getLength()const {
	if (!isEmpty()) {
		LinkNode<T>*p = head->next;
		int index = 0;
		while (p)
		{
			index++;
			p = p->next;
		}
		return index;
	}
	return 0;
}
//获取
template<class T>
T LinkList<T>::getData(int index) {
	T value=false;
	if (index<1 || index>this->getLength()) {
		cout << "获取元素失败!!!" << endl;
		return value;
	}
	else {
		LinkNode<T>*p = head;
		LinkNode<T>*q = NULL;
		for (int i = 1; i < index; i++)
		{
			p = p->next;
		}
		q = p->next;
		value= q->data;
	}
	return value;
}
//修改
template<class T>
bool LinkList<T>::modifyData(int index, const T&x) {
	if (index<1 || index>this->getLength()) {
		cout << "修改元素失败!!!" << endl;
		return false;
	}
	else {
		LinkNode<T>*p = head;
		for (int i = 0; i < index; i++)
		{
			p = p->next;
		}
		p->data = x;
		return true;
	}
}
//查找
template<class T>
int LinkList<T>::find(const T&x) {
	LinkNode<T>*p = head->next;
	int index = 1;
	while (p!=NULL&&p->data!=x){
		index++;
		p = p->next;
	}
	if (p != NULL) {
		return index;
	}
	else {
		return 0;
	}
}
//重载运算符
template<class T>
void LinkList<T>::outPut(ostream&cout) {
	LinkNode<T>*p = head->next;
	while (p)
	{
		cout << p->data << " ";
		p = p->next;
	}
}
template<class T>
ostream&operator<<(ostream&cout,LinkList<T>&x) {
	x.outPut(cout);
	return cout;
}

主函数测试调用

#include<iostream>
using namespace std;
#include"linkList.h"

int main() {
	LinkList<int>linkList;
	linkList.insert(1,100);
	linkList.insert(1,200);
	linkList.insert(26,300);
	linkList.insert(3,400);
	cout << "当前链表元素有:" << linkList << endl;
	cout << "当前链表的长度为:" << linkList.getLength() << endl;
	cout << "当前链表中200的位置:" << linkList.find(200) << endl;
	cout << "当前链表中100的位置:" << linkList.find(100) << endl;
	cout << "当前链表中300的位置:" << linkList.find(3060) << endl;
	cout << "当前链表中200的位置:" << linkList.find(400) << endl;
	cout << "获取链表1中元素:" << linkList.getData(1) << endl;
	cout << "获取链表2中元素:" << linkList.getData(2) << endl;
	cout << "获取链表3中元素:" << linkList.getData(3) << endl;
	cout << "获取链表4中元素:" << linkList.getData(45) << endl;
	cout << "修改链表中400元素:" << linkList.modifyData(4,40) << endl;
	cout << "当前链表元素有:" << linkList << endl;
	linkList.deleteByIndex(15);
	cout << "当前链表元素有:" << linkList << endl;
	linkList.insert(1,200);
	linkList.deleteByKey(407);
	cout << "当前链表元素有:" << linkList << endl;
	cout << "当前链表的长度为:" << linkList.getLength() << endl;
	cout << "获取链表1中元素:" << linkList.getData(1) << endl;
	system("pause");
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值