一. 引言
链式存储结构,又叫链接存储结构。在计算机中用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的).链式存储结构相对于顺序存储结构而言存储密度小,插入、删除灵活,逻辑上相邻的节点物理上不必相邻,查找结点时链式存储要比顺序存储慢。下面介绍链式存储结构的一种简单形式单链表结构及其c++实现。
二. 单链表的结构及基本操作
单链表的每一个单元成为结点,每个结点包含数据域和指针域,数据域用于存放数据data,指针域用于存放指向下一个结点的指针next。每个单链表必然存在一个头指针head,头指针用于指向头结点,头指针是单链表存在的必要条件。通常头结点的数据域不存放任何信息或用于存放链表长度,指针域用于指向下一个结点。如果头结点的指针域的指针指向的下一个结点为空,则该链表为空链表。非空链表的最后一个结点的指针域指针指向NULL。
1. 基本结构
1) 空链表
2)非空链表
2. 基本操作
1)单链表的头结点后插入结点操作
2)单链表尾部插入结点操作
单链表的尾部结点插入操作的时间复杂度为O(n),因为首先要构造指针遍历单链表的所有结点,找到尾结点,然后在其后面插入结点。
3)单链表中间某位置插入结点
例如,链表的数据为a, b, c, e,我们希望在e的前面插入d元素,基本操作如下图所示:
4)链表的反转操作
5)链表替换某结点的值
遍历结点找到对应结点然后替换。
6)删除链表某结点
7)打印链表内容
3. C++代码
类代码:
#include<iostream>
using namespace std;
template<typename T>
class LinkList{
public:
LinkList(){ init(); };
LinkList(const LinkList &rhs);
~LinkList();
void InsertHead(const T& v);
void InsertTail(const T& v);
void Insert(const T& d, const T& v);
void Erase(const T& d);
void Update(const T& d, const T& v);
void Reverse();
void Printer();
private:
struct Node{
T data;
Node* next;
Node(const T& d = T(), Node* n = NULL) :data(d), next(n){}
};
Node* head; //定义头节点
int length;
void init(){ //初始化链表
length = 0;
head = new Node;
}
Node* Find(const T& d){
Node* p = head;
while (p){
if (p->next->data == d)
break;
p = p->next;
}
return p;
}
};
template<typename T>
LinkList<T>::LinkList(const LinkList &rhs){
init();
*this = rhs;
}
template<typename T>
LinkList<T>::~LinkList(){
Node* p = NULL;
while (head->next != NULL){
p = head->next;
head->next = p->next;
delete p;
}
}
template<typename T>
void LinkList<T>::Insert(const T& d, const T& v){
Node* p = Find(d);
Node* q = new Node(v);
q->next = p->next;
p->next = q;
}
template<typename T>
void LinkList<T>::Erase(const T& d){
Node* p = Find(d);
Node* q = p->next;
p->next = p->next->next;
delete q;
}
template<typename T>
void LinkList<T>::Update(const T& d, const T& v){
Node* p = Find(d);
p->next->data = v;
}
template<typename T>
void LinkList<T>::InsertHead(const T& v){
Node* p = new Node(v);
p->next = head->next;
head->next = p;
}
template<typename T>
void LinkList<T>::InsertTail(const T& v){
Node* p = head;
Node* q = new Node(v);
while (p->next)
p = p->next;
p->next = q;
q->next = NULL;
}
template<typename T>
void LinkList<T>::Printer(){
for (Node* p = head->next; p; p=p->next){
cout << p->data << " ";
}
cout << endl;
}
template<typename T>
void LinkList<T>::Reverse(){
Node* p = head->next;
Node* q = head->next->next;
Node* m = head->next->next->next;
head->next->next = NULL;
while (m){
q->next = p;
p = q;
q = m;
m = m->next;
}
q->next = p;
head->next = q;
}
测试代码:
#include<iostream>
#include"LinkList.h"
using namespace std;
int main()
{
LinkList<int> List;
List.InsertHead(1);
List.InsertHead(2);
List.InsertHead(4);
List.InsertHead(6);
List.Printer();
List.Reverse();
List.Printer();
List.InsertTail(7);
List.Printer();
List.Insert(4, 3);
List.Insert(6, 5);
List.Printer();
List.Erase(7);
List.Printer();
List.Update(3, 7);
List.Printer();
LinkList<int> List1 = List;
List1.Printer();
return 0;
}
测试结果: