线性表的链式表示和实现
单链表
链式结构的特点是用一组任意的存储元素来存储线性表的元素,在内存中可以是连续的也可以是不连续的。对于单链表来说,存储数据元素除了本身信息外(数据域),还要存储指示其直接后续的信息(指针域)。
struct Node
{
int data;
Node *next;
};
class LinkList
{
Node *head;
public:
LinkList(){ head = new Node; head->next = NULL; };
~LinkList(){ delete head; };
void Create(int n); //创建长度为n的单链表
int GetElem(int i); //获取第i个元素
int Locate(int e); //返回第一个与e匹配的元素位序
bool IsEmpty(){ return (head->next == NULL); }//判断是否为空表
int Prior(int e); //e的前驱
int Next(int e); //e的后续
void Insert(int x, int i); //将x插入到i位置
int Delete(int i); //删除表中第i个元素
void Clear(); //清空
void Print(); //输出
};
结构体Node用来表示链表的每一个元素分别是数据域和它的指针域;
取元素
int LinkList::GetElem(int i){
Node *p;
int k, j;
if (head->next == NULL)
{
cout << "表为空" << endl;
exit(0);
}
else
{
p = head;
k = 0;
while (p && k<i)
{
p = p->next;
k++;
}
if (!p||k>i)
{
cout << "第" << i << "个元素不存在" << endl;
exit(0);
}
return(p->data);
}
}
时间复杂度O(n);
插入操作
void LinkList::Insert(int x, int i){
Node *p = head;
int k = 0;
while (p && k<i-1)
{
p = p->next;
k++;
}
if (!p||k>i-1)
{
cout << "第" << i - 1 << "个元素不存在" << endl;
exit(0);
}
Node *s = new Node;
if (!s)
{
cout << "空间分配失败" << endl;
exit(0);
}
s->data = x;
s->next = p->next;
p->next = s;
}
删除操作
int LinkList::Delete(int i){
Node *p = head;
int k = 0;
while (p&&k<i-1)
{
p = p->next;
k++;
}
if (!p||p->next==NULL)
{
cout << "删除位置非法" << endl;
exit(0);
}
Node *q = p->next; //暂存删除节点
p->next = q->next; //删除
int e = q->data;
delete q;
return e;
}
建立单链表
void LinkList::Create(int n){
Node *p;
for (int i = 0; i < n; i++)
{
p = new Node;
cin >> p->data;
p->next = head->next;
head->next == p;
}
}
双向链表
双向链表与单链表相比,最大的不同就是双向链表的元素不仅有数据和后续指针,它还有前驱的指针。通过一个节点不仅可以向前查找,也可以向后查找。
struct DNode
{
int data;
DNode *prior; //前驱指针
DNode *next; //后续指针
};
class DBList
{
DNode *head;
public:
DBList(){ head = new DNode; head->next = NULL; head->prior == NULL; };
~DBList();
void Create(int n); //创建长度为n的双链表
int GetElem(int i); //取表中第i个元素
DNode Locate(int e); //返回第一个与e匹配的节点指针
bool IsEmpty();
void Insert(int x, int i);
int Delete(int i);
void Clear();
};
在双链表中,有些操作如取元素,求表长,定位等,只涉及一个方向的指针,则这些操作的算法描述和单链表相同。但在进行插入,删除操作时有很大的不同,在双链表中需同时修改两个方向上的指针,还要小心修改顺序。
双链表的节点删除操作
p -> prior -> next = p -> next;
if(!p->next)
p -> next -> prior = p -> prior;
双链表的节点插入操作
s = new DNode;
s -> data = e;
s -> prior = p -> prior;
p -> prior = next = s;
p -> prior = s;
s -> next = p;
循环链表
循环链表是线性链表的一种变形,一般的链表结构最后一个节点的指针域为空,表示链表的结束。若使最后一个节点的指针指向头节点,则链表呈环状,称循环链表。
小结
链式存储结构特点:
优点:
1.节点空间的动态申请和动态释放,克服了顺序存储结构中需要预先设定数据元素的最大个数的缺点。
2.数据元素之间的次序是用指针来控制的,不像在顺序存储结构中进行插入,删除时需要移动大量数据元素。
缺点:
1.每个节点的指针域需要额外的存储空间,特别是当每个节点的数据域所占空间不是很大时,指针域所占空间就会显得很大。
2.链式存储结构是一种非随机存储结构,不能直接访问,从而增加了算法的时间复杂度。