链式存储结构:
这些代码都是伪代码,不能直接用的,仅供参考。因为一开始是在word上面写的,有的代码中每一行的首字母自动变成大写了,有的改过来了,有的可能漏了,不好意思(^ O ^)
定义:
- 用一组物理位置任意的存储单元来存放线性表的数据元素。
- 链表中的元素的逻辑次序和物理次序不一定相同。
- 单链表是由头指针唯一确定,可以用头指针的名字来作为单链表的名字。
和链式存储有关的术语:
结点:数据元素的存储映像。又数据域和指针域两部分组成。
链表:n个节点由指针链组成一个链表。它是线性表的链式存储映像。
单链表:结点只有一个指针域的链表。
双链表:结点有两个指针域的链表。
循环链表:首尾相连的链表。
头指针:指向链表中第一个节点的指针。
首元结点:链表中存储第一个数据的节点。
头结点:在首元结点前附加的一个节点。
表示空表:
无头结点时:头指针为空时为空表;
有头结点时:头结点的指针域为空时为空表。
结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。
访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其余结点,所以寻找第一个节点和最后一个节点所花费的时间不等
Typedef struct Lnode{ //声明结点的类型和指向结点的指针类型
EleType data; //结点的数据域
Struct Lnode *next; //结点的指针域
}node, *LinkList; //LinkList为指向结构体Lnode的指针类型
单链表的初始化(构造一个空表):
生成新结点做头节点,用头指针L指向头结点;
将头结点的指针域置空。
Status InitList_L(LinkList &L){
L=new LNode; //或L=(LinkList )malloc (sizeof(LNode));
L->next=NULL;
return OK;
}
判断链表是否为空:
int ListEmpty(LinkList L){//若L为空表,则返回1,否则返回0
if (L->next)//非空
return 0;
else
return 1;
}
删除链表:
Status DestoryList_L(LinkList &L){
Lnode *p; //或LinkList p;
while(L){
p=L;
L=L->next;
delete p;
}
return OK;
}
清空链表:
Status ClearList(LinkList &L){//将L重置为空表
Lnode *p,*q;//或LinkList p,q;
p=L->next;
while(p){//没到表尾
q=p->next;
delete p;
p=q;
}
L->next=NULL;//头节点指针域为空
return OK;
}
求单链表的表长:
int ListLength_L(LinkList L){//返回L中数据元素的个数
LinkList p;
p=L->next;//p指向第一个节点
i=0;
while(p){//遍历单链表,统计结点数
i++;
p=p->next;
}
return i;
}
回顾总结:
1.类型定义
Typedef struct LNode{
ElemType data;
Struct LNode *next;
}LNode, *LinkList;
2.变量定义:
LinkList L;
LNode *p,*s;
3.重要操作:
P=L;//p指向头节点
S=L->next;//s指向首元结点
P=p->next;//p指向下一节点
获得第i个元素的值:O(n)
Status GetElem_L(LinkList L, int i, ElemType &e){//获取线性表L中的某个数据元素的内容,通过变量e返回
P=L->next;j=1;//初始化
While(p&&j<i){//向后扫描,直到p指向第i个元素或p为空
P=p->next;++j;
}
If(!p||j>i) return ERROR;//第i个元素不存在
E=p->data; //取第i个元素
Return OK;
}
查找:O(n)
Lnode *LocateElem_L(LinkList L, Elemtype e){
//在线性表L中查找值为e的数据元素
//找到,返回L中值为e的数据元素的地址,查找失败返回NULL;
p=L->next;
while(p&&p->data!=e){
p=p->next;
j++;
}
if(p) return j;
else return 0;
}
插入节点:O(n)
Status ListInsert_L(LinkList &L,int i,ElemType e){
p=L,j=0;
while(p&&j<i-1){p=p->next;++j;}//寻找第i-个节点,p指向i-1结点
if(!p||j>i-1) return ERROR;//i>表长+1或者<1,插入位置非法
s=new LNode; s->data=e;//生成新结点s,将结点s的数据域置为e
s->next=p->next;//将节点s插入L中
p->next=s;
return OK;
}//ListInsert_L;
删除第i个结点:O(n)
Status ListDelete_L(LinkList &L,int i,ElemType &e){
p=L,j=0;
while(p&&j<i-1){p=p->next;++j;}//寻找第i-个节点,p指向i-1结点
if(!p||j>i-1) return ERROR; //i>表长+1或者<1,插入位置非法
q=p->next; //临时保存被删结点的地址以备释放
p->next=q->next; //改变删除节点前驱结点的指针域
e=q->data; //保存删除节点的数据域
delete q; //释放删除结点的空间
return OK;
}//ListDelete_L;
单链表的建立:
头插法:
void CreatList_H(LinkList &L,int n){
L=new node;
L->next=NULL;
for(i=n;i>0;i--){
p=new LNode;
cin>>p->data;
p->next=L->next;
L->next=p;
}
}//CreatList_H
后插法:
void CreatList_R(LinkList &L,int n){
L=new LNode;
L->next=NULL;
r=L; //尾指针r指向头节点
for(i=0;i<n;i++){
p=new LNode;
cin>>p->data; //生成新结点,输入元素值
P->next=NULL;
r->next=p; //插入到表尾
r=p; //r指向新的尾节点
}
}//CreatList_R