为什么要使用链表
数组是程序设计语言中的一种比较有用的数据结构,但是数组也存在其本身的局限性:
1. 编译期间需要明确指定大小
2. 数组中的数据在计算机内存中是连续的,也就是说每个元素在内存中的间隔是相同的,当要在数组中插入或删除一个元素时,需要移动该数组中的其它数据。
而这些问题在链表中是不存在的,链表由一个个节点组成,节点中保存着属于该节点的信息和指向下一个节点的指针。通过这种方式,节点可以分布在内存中的任意位置,这对于内存的有效利用是很方便的。
什么是链表
链表是一种由节点组成的数据结构,每个节点都包含某些信息和指向链表中另外一个节点的指针。
如果序列中的节点只包含指向后继节点的 链接,该链表就称为单向链表。
由于链表的定义过于简单,这里不做过多叙述。以下是用 c++ 实现的单向链表。
// linked_lists.h
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
using std::ostream;
using std::cout;
using std::endl;
/*
定义一个节点类,其中包含一个信息成员 info,一个指针成员 next
*/
class Linked_list_node
{
public:
int info;
Linked_list_node *next;
public:
Linked_list_node()
{
info = 0;
next = nullptr;
}
Linked_list_node(int i = 0, Linked_list_node *p = nullptr)
{
info = i;
next = p;
}
~Linked_list_node() {};
};
class One_way_linked_list
{
public:
Linked_list_node *head, *tail;
public:
One_way_linked_list()
{
head = tail = nullptr;
}
bool isempty()
{
return head == nullptr;
}
bool inlist(int) const; // 表明不能修改 this 指针指向的对象
void addtohead(int);
void addtotail(int);
int deletefromhead();
int deletefromtail();
void deleteselect(int);
friend ostream & operator<<(ostream&, const One_way_linked_list &);
~One_way_linked_list();
};
#endif // !LINKED_LIST_H
// linked_lists.cpp
#include <iostream>
#include "linked_lists.h"
bool One_way_linked_list::inlist(int i) const
{
Linked_list_node *tmp;
for (tmp = head; tmp != nullptr && !(tmp->info == i); tmp = tmp->next);
return tmp != nullptr;
}
void One_way_linked_list::addtohead(int i)
{
head = new Linked_list_node(i, head);
if ( tail == nullptr )
{
tail = head;
}
}
void One_way_linked_list::addtotail(int i)
{
if (tail != nullptr)
{
tail->next = new Linked_list_node(i);
tail = tail->next;
}
else
head = tail = new Linked_list_node(i);
}
int One_way_linked_list::deletefromhead()
{
int i = head->info;
if (head == tail)
head = tail = nullptr;
else
head = head->next;
return i;
}
int One_way_linked_list::deletefromtail()
{
int i = tail->info;
if (head == tail)
head = tail = nullptr;
else
{
Linked_list_node *tmp;
for (tmp = head; tmp->next != tail; tmp = tmp->next);
delete tail;
tail = tmp;
tail->next = nullptr;
}
return i;
}
void One_way_linked_list::deleteselect(int i)
{
if (head != nullptr)
{
if (head == tail && i == head->info)
head = tail = nullptr;
else if (i == head->info)
head = head->next;
else
{
Linked_list_node *pred, *tmp;
for (pred = head, tmp = head->next; tmp != nullptr && !(tmp->info == i); \
pred = pred->next, tmp = tmp->next);
if (tmp != nullptr)
{
pred->next = tmp->next;
if (tmp == tail)
tail = pred;
}
}
}
}
ostream & operator<<(ostream& out, const One_way_linked_list & p)
{
Linked_list_node *tmp;
for (tmp = p.head; tmp != nullptr; tmp = tmp->next)
out << tmp->info << " ";
return out;
}
// create_list.cpp
#include <iostream>
#include "linked_lists.h"
int main()
{
using namespace std;
//*********此处是单向链表测试代码********
One_way_linked_list list1;
cout << list1.isempty() << endl;
list1.addtohead(1);
list1.addtohead(2);
list1.addtohead(3);
list1.addtohead(4);
list1.addtotail(5);
list1.addtotail(6);
list1.addtotail(7);
list1.addtotail(8);
list1.deletefromhead();
list1.deletefromhead();
list1.deletefromtail();
list1.deletefromtail();
list1.deleteselect(5);
list1.deleteselect(12);
cout << list1.inlist(1) << endl;
cout << list1.inlist(10) << endl;
cout << list1.isempty() << endl;
cout << list1 << endl;
//***********************************/
system("pause");
return 0;
}
参考资料:
1. C++数据结构与算法:https://item.jd.com/29739898993.html