文章目录
线性表链式存储
头指针H,数据域,指针域。单链表由头指针唯一定义。
链式表示与实现
概念
- 结点:数据元素的存储映像。由数据域和指针域组成
- 链表:n个结点由指针链组成一个链表
- 单链表:只有一个指针域
- 双链表:由两个指针域,有前驱和后驱
- 循环链表: 首尾相接
- 头指针:指向链表的第一个结点的指针
- 首元结点:存储第一个数据元素的结点
- 头结点:首元结点前附设的一个结点
表示空表:无头节点,头指针为null;有头节点,头节点的指针域为null
头结点的数据域:可以空或者放表长
链表的特点:
数据域域指针域变量类型
- data float、int elemtype
- next:(int*) p
- 取地址 p = &a
typedef int ElemType;
typedef struct Lnode {
ElemType data; // data
struct Lnode *next; // 指针
}Lnode,*LinkList; // LinkList为指向结构体Lnode的指针类型
嵌套定义
单链表基本操作的实现
初始化
- 算法步骤
- 生成新节点作为头结点,用头指针指向头结点
- 将头结点指针域置空
Status InitList_L(LinkList &L) {
L = new Lnode;
L->next = NULL;
return OK;
}
判断是否为空
Status ListEmpty(LinkList L) {
if (L->next)
return 0;
else
return 1;
}
单链表销毁
Status ListDelete(LinkList &L) {
Lnode* p;
while (L) {
p = L;
L = L->next;
delete p;
}
return OK;
}
清空
Status ClearList(LinkList& L) {
Lnode* p,* q;
p = L->next;
while (p) {
q = p->next;
delete p;
p = q;
}
L->next = NULL;
return OK;
}
求链表表长
Status ListLength(LinkList L) {
Lnode* p;
int count = 0;
p = L->next;
while (p) {
count++;
p = p->next;
}
return count;
}
取值
Status GetElem_L(LinkList L, int i, ElemType &e) {
p = L->next;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i) return ERROR;
e = p->data;
return OK;
}
查找
- 按值查找
- 返回序号
Status FindElem_L(LinkList L, ElemType e) {
p = L->next;
int j = 1;
while (p&&p->data != e) {
p = p->next;
j++;
}
if(p) return j;
else return NULL;
}
返回地址
Lnode* LocateElem_L(LinkList L, ElemType e) {
p = L->next;
while (p&&p->data!=e) {
p = p->next;
}
return p;
}
O(n)
插入
Status ListInsert(LinkList &L, int i, ElemType e) {
p = L;
int j = 0;
while (p && j<i-1) {
p = p->next;
j++;
}
if (!p || j > i - 1) return ERROR;
Lnode* s = new Lnode;
s->next = p->next;
p->next = s;
return OK;
}
O(n)+O(1)
删除
Status ListDelete(LinkList &L, int i, ElemType &e) {
p = L;
int j = 0;
while (p && j < i - 1) {
p = p->next;
j++;
}
if (!p || j > i - 1) return ERROR;
Lnode* q = p->next;
p->next = q->next;
e = q->data;
delete q;
return OK;
}
O(n)+O(1)
单链表建立
头插法(前插法)
void ListSetup(LinkList& L, int n) {
Lnode* L = new Lnode;
L->next = NULL;
for (int j = n; j > 0; j--) {
Lnode* p = new Lnode;
cin>>p->data;
p->next = L->next;
L->next = p;
}
}
O(n)
尾插法(后插法)
void ListSetup_R(LinkList& L, int n) {
Lnode* L = new Lnode;
L->next = NULL;
Lnode* r = L;
for (int j = 0; j < n ; j++) {
Lnode* p = new Lnode;
cin >> p->data;
p->next = NULL;
r->next = p;
r = p;
}
}
循环链表基本操作的实现
如果经常操作首位数据,带尾指针的循环列表更方便。
连接两个表
LinkList Connect(LinkList Ta, LinkList Tb) {
LinkList p = Ta->next;
Ta->next = Tb->next->next; //Tb表头连Ta表尾
delete Tb->next;
Tb->next = p;
return Tb;
}
双向链表以及双向循环基本操作的实现
typedef struct DuLnode {
ElemType data; // data
struct DuLnode* prior,* next; // 指针
}* DuLnode, * DuLinkList; // LinkList为指向结构体Lnode的指针类型
双向链表结构对称性:
p->prior->next = p = p->next->prior;
双向链表的插入与删除
Status ListInsert(DuLinkList& L, int i, ElemType e) {
DuLinkList p = GetElem_Dul(L, i);
if(!p) return ERROR;
DuLinkList s = new DuLnode;
s->data = e;
s->prior = p->prior;
p->prior->next = s;
s->next = p;
p->prior = s;
return OK;
}
Status ListDelete(DuLinkList& L, int i) {
DuLinkList p = GetElem_Dul(L, i);
if (!p) return ERROR;
p->prior->next = p->next;
p->next->prior = p->prior;
delete p;
return OK;
}