线性表-链式储存(链表)
链表的优点是容易扩展容量,缺点是不易进行随机存储,即读取某个元素时,需要从第一个元素开始慢慢读取。
链表可分为单链表、双链表、循环链表和静态链表。
1. 单链表
1.1 单链表定义
单链表中每个数据内存中不只存放着单个元素的数据元素,还存放着指向下一个节点的指针。
1.1.1 单链表定义代码
//c++代码
struct LNode
{
int data; //存放数据
LNode * next;//指向下一个节点的指针
};
1.2单链表的插入和删除
1.2.1 按位序插入(带头结点)
//带头节点的结点插入
bool ListInsert1(LinkList &L,int i, int e)//在第i个元素位置插入结点e
{
if (i < 1)
return false;
//前一部分为了找到指向第i-1个结点的指针
LNode *p = L;//L指向的为头结点
int j = 0;//当前p指向的是第几个结点
while (p != NULL and j < i - 1)
{
p = p->next;
j++;
}
if (p == NULL)
return false;
//后一部分为了将第i个元素插入进去
LNode *s = new(LNode);
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
1.2.2 按位序插入(不带头结点)
//不带头节点的结点插入
bool ListInsert2(LinkList &L, int i, int e)
{
//不带头节点的结点插入
if (i == 1)
{
LNode *s = new(LNode);
s->next = L;
s->data = e;
L = s;//头指针重新指向新结点
return true;
}
LNode *p = L;
int j = 1;
while (p != NULL and j < i - 1)
{
p = p->next;
j++;
}
if (p == NULL)
{
return false;
}
LNode *s = new(LNode);
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
1.2.3 指定结点的后插操作
//指定结点的后插操作
bool InsertNextNode(LNode *p, int e)
{
if (p == NULL)
{
return false;
}
LNode *s = new(LNode);
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
1.2.4 指定结点的前插操作
//指定结点的前插操作
bool InsertPriorNode1(LNode *p, int e)
{
if (p == NULL)
return false;
LNode *s = new(LNode);
s->data = p->data;
p->data = e;
s->next = p->next;
p->next = s;
return true;
}
1.2.5 按位序删除
//带头结点的按位序删除
bool ListDelete(LinkList &L, int i, int &e)
{
LNode * p = L;
int j = 0;
while (p != NULL and j < i-1 )
{
p = p->next;
j++;
}
if (p == NULL)
return false;
LNode *s = new (LNode);
s = p->next;
e = s->data;
p->next = s->next;
delete s;
return true;
}
1.2.6 指定结点的删除
//指定结点的删除
bool DeleteNode(LNode *p)
{
if (p == NULL)
return false;
if (p->next == NULL)
return false;
LNode *s = new(LNode);
s = p->next;
p->data = p->next->data;
p->next = s->next;
delete(s);
return true;
}
1.3 单链表的查找(带头节点的单链表)
1.3.1 单链表的按位查找
//按位查找
LNode *GetElem(LinkList L, int i)
{
if (i < 0)
return false;
LNode *p = L;
int j = 0;
while (p != NULL and j < i)
{
p = p->next;
j++;
}
return p;
}
1.3.2 单链表的按值查找
//按值查找
LNode *LocateElem(LinkList L, int e)
{
LNode *p = L->next;
while (p != NULL && p->data != e)
{
p = p->next;
}
return p;
}
1.4 单链表的长度求解
int length(LinkList L)
{
LNode *p = L->next;
int length = 0;
while (p != NULL)
{
p = p->next;
length++;
}
return length;
}
1.5 单链表的建立方法
头插法与尾插法本质都是在特定结点的后插,只是头插法是始终在头结点的后插;尾插法是在尾指针的后插。
1.5.1 头插法
头插法可以导致数据逆置。
//头插法建立单链表
LinkList List_HeadInsert(LinkList &L)
{
L->next = NULL;
int x;
cin >> x;
while (x != 9999)
{
LNode *s = new(LNode);
s->data = x;
s->next = L->next;
L->next = s;
cin >> x;
}
return L;
}
1.5.2 尾插法
//尾插法建立单链表
LinkList List_TailInsert(LinkList &L)
{
//定义一个尾指针
LNode *r = L;
LNode *s ;//s指向新添加的数据结点
L->next = NULL;
int x;
cin >> x;
while (x != 9999)
{
s = new(LNode);
s->data = x;
r->next = s;
r = s;
cin >> x;
}
r->next = NULL;
return L;
}