数据结构C++(1)单链表及其各函数实现的详细算法
数据结构之线性表中的链表
线性表是一种最简单.最基本也是最常用的线性结构,在线性结构中,数据元素之间存在一个对一个的线性关系,数据元素一个接一个地排列,而在一个线性表中数据元素的类型是相同的(由同一个类型的数据元素组成)。简单的线性表分为顺序结构和链式结构,一般顺序结构在C++中使用数组表示,方法相对简单,但相应的它所能够实现的功能有一定的局限性,比如在进行插入,删除等时候比较繁琐。而链式结构用指针节点进行“首尾相接”实现了逻辑关系上的相邻,因此它对线性表的插入,删除等操作更加容易。
链表是通过一组任意的存储单元来存储线性表中的数据元素,链表的实现方法有很多种,而使用指针是其中相对最灵活最易用的一种
算法
在链表算法中,如果一个节点将指向另一个节点的指针当作数据成员,那么多个这样的节点可以链接起来,到时候只需要用一个变量就能够访问整个节点序列。可以说链表是一种由节点组成的数据结构,每个节点都包含某些信息和指向另一个节点的指针,如果序列中的节点只包含指向后续节点的指针(或链接),那么该链表就是单链表。
对于单链表更加详细的来说,我们只需要一个变量来遍历链表中的每一个元素即可,一般我们设置头,尾两个指针方便我们对单链表进行增删改查(可以理解为我们用一个额外的变量在头和尾指针的共同定位下进行相关操作,大多数算法可以是这个思路),在这个基础上,增删改查也只需要改动特定节点的指针数据就行了
具体代码实现
我们先构建节点类
节点类:
class Node {
public:
int data;//数据
Node* next;//指向下一个节点的指针
Node()
{
next = 0;
}
Node(int a, Node* point)
{
data = a;
next = point;
}
Node(int a)
{
data = a;
}
};//声明结点类
链表类(核心在于其中指针的灵活运算):
class List
{
public:
List() {
head = tail=0 ;
}
~List();
//判空
int isempty()
{
return head == 0;
}
//在头节点添加
void addtohead(int);
//在尾节点添加
void addtotail(int);
//删除第一个节点
int deletehead();
//删除最后节点
int deletetail();
//删除指定一类数据的节点
void deleteNode(int);
//判断是否删除
bool isinlist(int)const;
//打印链表
void putout();
protected:
Node* head, * tail;
};
List::~List() {
for (Node* p; !isempty();)
{
p = head->next;
delete head;
head = p;
}
}
void List::addtohead(int info) {
head = new Node(info, head);
if (tail == 0)
tail = head;
}
void List::addtotail(int info) {
if (tail != 0)//判空
{
tail->next = new Node(info);
tail = tail->next;
}
else head = tail = new Node(info);
}
int List::deletehead()
{
int info = head->data;
Node* tmp = head;
if (head == tail)//当只存在一个节点时
head = tail = 0;
else head = head->next;
delete tmp;
return info;
}
int List::deletetail()
{
int info = tail->data;
if (head == tail)//当只有一个节点时
{
delete head;
head = tail = 0;
}
else {
Node* tmp;//记录tail节点的前一个节点
for (tmp = head; tmp->next != tail; tmp = tmp->next);
delete tail;
tail = tmp;//原来倒数第二个节点成为tail节点
tail->next = 0;
}
return info;
}
void List::deleteNode(int info)
{
if(head!=0)//判空
if (head == tail && info == head->data)//当只有一个节点时
{
delete head;
head = tail = 0;
}
else if (info == head->data)
{
Node* tmp=head;
head = head->next;
delete tmp;
}
else {
Node* p, * tmp;
//遍历寻找
for (p = head, tmp = head->next/*从头节点之后开始*/; tmp != 0 && !(tmp->data == info)/*寻找要删除的数据*/; p = p->next, tmp = tmp->next);
if (tmp != 0) {
p->next = tmp->next;
if (tmp == tail)//调整尾节点
tail = p;
delete tmp;
}
}
}
bool List::isinlist(int info)const {
Node* tmp;
for (tmp = head; tmp != 0 && !(tmp->data == info); tmp = tmp->next);
return tmp != 0;
}
void List::putout() {
if (tail==0)
cout << "链表为空" << endl;
else {
Node* p = head;
if(head==tail)//只有一个节点时
cout<<p->data << endl;
else
{
for (p; p != tail; p = p->next)
{
cout << p->data << " ";
if (p->next == tail)
cout << p->next->data << " ";
}
cout << endl;
}
}
}
测试代码:
#include<iostream>
#include"List.h"
#include"Node.h"
using namespace std;
int main()
{
List l;
l.isempty();
cout << "在链表前添加5:" << endl;
l.addtohead(5);
l.putout();
cout << "在链表前添加6:" << endl;
l.addtohead(6);
l.putout();
cout << "在链表前添加7:" << endl;
l.addtohead(7);
l.putout();
cout << "在链表后添加4:" << endl;
l.addtotail(4);
l.putout();
cout << "在链表后添加3:" << endl;
l.addtotail(3);
l.putout();
cout << "在链表后添加2:" << endl;
l.addtotail(2);
l.putout();
cout << "删除第一个元素:" << endl;
l.deletehead();
l.putout();
cout << "删除最后一个元素:" << endl;
l.deletetail();
l.putout();
cout << "删除4元素:" << endl;
l.deleteNode(4);
l.putout();
return 0;
}
运行结果
代码较为简单易懂,希望大家多多斧正!