c++链表
主函数文件:
#include <iostream>
#include "list_t.h"
using namespace std;
int main()
{
list_t lin; // 定义类对象 lin
lin.append(3); //
lin.append(4);
lin.append(7);
lin.append(67);
lin.append(98);
lin.append(23);
lin.insertHead(1998);
cout << lin; //输出类对象lin
lin.delNode(67);
cout << lin;
lin.delNode(23);
cout << lin;
//lin.delNode(&lin);
lin.find(2);
cout << "Hello World!\n";
}
类与函数声明及函数实现文件
#pragma once
#include <iostream> //输出重载时调用
using namespace std;
struct list_node //双向链表元素结构体
{
int data; //***元素数据,用于存储数据***
list_node *next; //
$元素指针,访问节点,对数据进行操作
$元素指针,访问节点,对数据进行操作
$
list_node *prev;
};
class list_t //类的定义,用类来实现对链表数据的操作
{
private:
int size; //私用的三个类变量:链表元素个数,前一个元素结构体指针,后一个元素结构体指针
list_node * head;
list_node * tail;
public:
list_t(void); //类构造函数和析构函数
~list_t(void);
//声明类成员函数之一:判断要操作的链表是否为空(是否没有元素)
bool isEmpty(void);
//声明类成员函数之二三:对链表的头插与尾插
int insertHead(int d);
int append(int d);
//声明类成员函数之四五:对链表中指定的元素与指定的数据进行删除
int delNode(list_node * node);
int delNode(int d);
//声明类成员函数之六: 对链表中的指定数据进行查找
list_node * find(int d);
//声明类的友元输出运算符重载函数,
friend ostream & operator<<(ostream & out, const list_t & li);
};
//实现类构造函数和析构函数
list_t::list_t(void)
{
head = tail = NULL; //初始化(清空)链表的元素及元素个数
size = 0;
}
list_t::~list_t(void)
{
}
//实现类成员函数之一:判断要操作的链表是否为空(是否没有元素)
bool list_t::isEmpty(void)
{
if(0 == size)
{
return true;
}
return false;
}
//实现类成员函数之二三:对链表的头插与尾插
int list_t::insertHead(int d) //元素头插, 入参为一个整型数据
{
list_node * li = new list_node; //1,定义并开辟链表指针 "li",给确定无疑的东西赋值处理
li->data = d; //!!!通过链表得元素中数据赋值,也可写为
(∗li).data=d;
(∗li).data=d;
$$$
li->prev = NULL;
//2,其次,当遇到简单的情况下,我们该怎么办?
//当链表为空时
if (isEmpty())
{
head = tail = li; //***给两个链表结构体指针(类内变量)进行 li的内存拷贝
size++; //元素个数加1
return size; //返回元素个数
}
//3,最后,遇到非简单的情况下我们又该怎么做?
//当链表不为空时
li->next = head; //头部插入元素的后向指针 变为 原链表头部结构体元素地址
head->prev = li; //原链表头部结构体元素的前向指针变为 头插插入的元素 li
head = li; //更新原链表头部结构体元素为 头插插入的元素 li
size++; //元素个数加1
return size; //返回元素个数
}
int list_t::append(int d) //元素尾插, 入参为一个整型数据
{
list_node * li = new list_node; //1,定义并开辟链表指针 "li",给确定无疑的东西赋值处理
(*li).data = d; //!!!通过链表得元素中数据赋值,也可写为
li−>data=d;
li−>data=d;
$$$
li->next = NULL; //尾部插入元素的后向指针显然是NULL,指向为空
//2,其次,当遇到简单的情况下,我们该怎么办?
//当链表为空时
if (isEmpty()) //???很奇怪,形参写入为void时报错,不写入时正确.
{
head = tail = li; //***给两个链表结构体指针(类内变量)进行 li 的内存拷贝
li->prev = NULL; //链表元素的前向指针赋值为空指针,因为现在的情况是该表中只有他一个元素!!!我们常常会忘掉前提条件
size++; //链表元素个数加1
return size; //返回链表元素个数
}
//3,最后,遇到非简单的情况下我们又该怎么做?
//当链表不为空时
tail->next = li; //(类内保存的)原链表尾部结构体元素的后向指针 更新为 li (打扫屋子)
li->prev = tail; //尾部插入元素的前向指针 变为 原链表尾部结构体元素的指针
tail = li; //将 原链表尾部结构体元素 更新为 新尾部插入的元素
size++; //元素个数加1
return size; //返回元素个数
}
////声明类成员函数之四五:对链表中指定的元素与指定的数据进行删除
//int list_t::delNode(list_node * node) //删除链表的一个结点(形参为该结点的地址)
//{
// if (isEmpty()) //若是空表则不删除
// {
// return 0;
// }
//
// list_node * tmp = head; //若不是空表,则内存拷贝一份头元素 命名为 tmp
// while (tmp)
// {
// if (tmp->data != node->data) //依据该结点的数据来遍历寻找这个结点(这不对,要是表中有至少两个元素数据一样就会产生误操作)
// {
// tmp = tmp->next; //遍历移位找出要删除的结点tmp
// continue;
// }
//
// if (head == tmp) //1.若要删除的结点是头结点时
// {
// head = head->next; //新的头结点就成为了 原头结点的后向指针
// head->prev = NULL; //新头结点的前向指针 变为 NULL
// delete tmp; //删除结点(释放指针的指向->变为随机地址值->变成野指针->危险(应处理为NULL))
// tmp = NULL;
// size--; //元素个数减1
// break;
// }
//
// if (tmp == tail) //若要删除的结点是尾结点时
// {
// tail = tail->prev; //新尾结点就成为了 原尾结点的前向结点
// tail->next = NULL; //新尾结点的后向指针 变为 NULL
// delete tmp; //删除结点(释放指针的指向->变为随机地址值->变成野指针->危险(应处理为NULL))
// tmp = NULL;
//
// size--; //元素个数减1
// break;
// }
// //2.若要删除的结点时中间结点时
// tmp->prev->next = tmp->next; //要删除结点的前1个结点的后向指针 指向 要删除结点的后1个结点
// tmp->next->prev = tmp->prev; //要删除结点的后1个结点的前向指针 指向 要删除结点的前1个结点
//
// delete tmp; //删除结点
// tmp = NULL;
// size--;
// break;
// }
// return size; //返回链表元素个数
//}
int list_t::delNode(int d) //删除链表的一个结点(形参为该结点的数据),同上面一样
{
if (isEmpty())
{
return 0;
}
list_node * tmp = head;
while (tmp)
{
if (tmp->data != d)
{
tmp = tmp->next;
continue;
}
if (head == tmp)
{
head = head->next;
head->prev = NULL;
delete tmp;
tmp = NULL;
size--;
break;
}
if (tmp == tail)
{
tail = tail->prev;
tail->next = NULL;
delete tmp;
size--;
break;
}
tmp->prev->next = tmp->next;
tmp->next->prev = tmp->prev;
delete tmp;
tmp = NULL;
size--;
break;
}
return size;
}
//实现类成员函数之六: 对链表中的指定数据进行查找
list_node * list_t::find(int d)
{
if (isEmpty())
{
return NULL;
}
list_node * tmp = head; //从头开始遍历查找,找到后返回元素指针,找不到则返回尾指针
while (tmp)
{
if (tmp->data == d)
{
break;
}
tmp = tmp->next;
}
return tmp;
}
//实现类的友元输出运算符重载函数,
ostream & operator<<(ostream & out, const list_t & li)
{
list_node * tmp = li.head; //从头遍历输出
out << "list content:"<<endl;
while (tmp)
{
out << tmp->data << " ";
tmp = tmp->next;
}
out << endl;
return out;
}
---------------------