链表
带头结点和不带头结点的区别:
-
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;
}