单链表
注意
- 一般情况下,为了处理方便,在单链表的第一个结点之前附设一个结点,称为头结点。
- 首元结点是指链表中存储第一个数据元素的结点。
- 头结点是在首元结点之前附设的一个结点。
- 头指针是指向链表中第一个结点的指针,增加头结点后,无论链表是否为空,头指针都是指向头结点的非空指针。
单链表存储结构
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList; //ListList为指向结构体LNode的指针类型
单链表初始化
步骤:
- 创建头结点
- 头结点指向为空
Status InitList(LinkList & L){
L=new LNode;
L->next=NULL;
return OK;
}
单链表取值
步骤:
- 创建一个结点指针指向首元结点
- 当指针指向不为空且不超出索引,指针后移
- 将得到的值赋值给引用变量e
Status GetElem(LinkList L,int i,ElemType &e){
LinkList 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;
}
单链表的查找
步骤:
- 创建一个结点指针指向首元结点
- 当指针不为空且指针所值的值不满足条件,指针后移
- 将得到的结点地址返回 若没有将返回NULL
LNode *LocateELem(LinkList L,ElemType e){
LinkList p=L->next;
while(e&&p->data!=e)
p=p->next;
return p;
}
单链表的插入
步骤:
- 生成一个结点指针p,指向链表的头结点
- 寻找插入位置的前一个位置,当没有到达指定位置,指针后移
- 生成新结点s,插入在p之后
Status ListInsert(LinkList &L,int i,ElemType e){
LinkList p=L;//指向头结点而不是首元结点,是因为有可能i为1,即链表首元结点
int j=0;
while(p&&j<i-1){//注意这里是i-1,因为插入的位置为i,前面有i-1个元素
p=p->next;
j++;
}
if(!p||j>i-1)
return ERROR;
LinkList s=new LNode;//插入p后面
s->date=e;
s->next=p->next;
p->next=s;
return OK;
}
单链表的删除
- 创建一个结点指针指向链表的首元结点
- 寻找删除结点的前一个元素,未到则指针不断后移
- 创建一个结点指针指向要删除的元素,以便内存释放
Status ListDelete(LinkList & L,int i){
LinkList p=L->next;
int j=0;
while(p&&j<i-1)[//i-1是因为要找到删除结点的前一个结点
p=p->next;
j++;
}
if(!p||j>i-1)
return ERROR;
//p->next=p->next->next;按道理可以这样,但是删除结点的地址未被释放
LinkList q=p->next;
p->next=q->next;
delete q;
return OK;
}
创建单链表(前插法和后插法)
前插法步骤:
- 创建头结点
- 创建新结点,将其插到头结点之后(即新插入结点为链表的首元结点)
void CreateList_H(LinkList & L,int n){
L=new LNode;
L->next=NULL;
LinkLNode p;
for(int i=0;i<n;i++){
p=new LNode;
cin>>p->data;
p->next=L->next;//将新结点插到头结点之后
L->next=p;
}
}
后插法步骤:
- 创建头结点
- 创建链表尾指针,指向头结点
- 将新结点插在尾结点之后,新结点称为尾结点
void CreateList_R(LinkList &L,int n){
L=new LNode;
L->next=NULL;
LinkList r=L;//将链表尾结点指向头结点
LinkLNode p;
for(int i=0;i<n;i++){
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
}
循环链表
注意
- 循环链表中最后一个结点的指针域指向头结点
- 在某些情况下,若在循环链表中设立尾指针而不设头指针,可以使操作简化(两个线性表合并可以将一方的尾指针指向另一方的第一个结点,然后释放其头结点)
p=B->next->next;//B的头结点
B->next=A->next->next;//B尾结点指向A头结点
A->next=p;//A尾结点指向B头结点
双向链表
定义
在双向链表的结点中有两个指针域,一个指向直接后继,另一个指向直接前驱
存储结构
typedef struct DulNode{
ElemType data;
struct DulNode *prior;
struct DulNode *next;
}DulNode,*DuLinkList;
结构特性
d->next->prior=d->prior->next=p;
双链表的插入
步骤:
- 寻找插入位置
- 建立新结点
- 进行指针修改,保证结点的不丢失
插在p之前,保证p的前项不丢失
Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
if(!(p=GetElem_Dul(L,i)))//在L中确定第i个元素的指针
return ERROE;
DuLinkList s=new DuNode;
s->data=e;
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;
return OK;
}
插在p之后,保证p的后项不丢失
Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
DuListLink p=L;
int j=0;
while(p&&j<i-1){
p=p->next;
j++;
}
if(!p||j>i-1)
return ERROR;
DuListLink s=new DulNode;
DulNode->data=e;
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
return OK;
}