定义一个结点
typedef struct ElemType{
char name[20];
int sex;
int age;
char number[11];
};
//定义一个结点
typedef struct Lnode{
ElemType data;
struct Lnode* next;
}LNode,*LinkList;
链表的初始化
一般包含两步:给结点分配空间,头指针指针域为空
相当于建立一个空表
/*链表初始化,头结点指针域为空 */
Status InitList_L(LinkList &L){ //L为指向头结点的指针
L=(LinkList)malloc(sizeof(LNode)); //L中存放着头结点的地址
L->next=NULL;
return OK;
}
单链表的简单操作
单链表的销毁
/*销毁单链表(头结点,头指针都不存在)*/
Status DestoryList_L(LinkList &L){ //L为指向头结点的指针
Lnode * p; //或者LinkList p;
while(L){
p=L; //p和L指向同一个结点
L=L->next; //L向后移动一个
free(p); //释放p
}
return OK;
}
清空单链表
/*清空单链表*/
Status ClearList(LinkList &L){
Lnode *p,*q;
p=L->next; //p指向首元结点
while(p){
q=p->next; //q指向p后面的结点
free(p); //释放p
p=q; //p,q指向同一结点
}
L->next=NULL;
return OK;
}
清空链表与销毁链表的不同在于:清空会保留单链表的头结点和头指针,相当于一个空表,而小胡链表,整个表都不存在。
求单链表的表长
/*求单链表的表长*/
int ListLength_L(LinkList &L){
LinkList p;
p=L->next; //p指向首元结点
int i=0;
while(p){ //遍历单链表
i++;
p=p->next;
}
return i;
}
单链表的基本操作
查找
取出链表中第i个元素的内容
/*取出链表中第i个元素的内容*/
//<1>从第一个结点顺着链表扫描,p=L->next;
//<2>j做计数器,初始值为1,记录已扫描的结点的个数
//<3>p向后移动,j++
//<4>当j==i时找到该结点
Status GetElem_L(LinkList &L,int i,ElemType &e){ /*通过变量e返回*/
LinkList p;
p=L->next;
j=1;
while(p&&j<i){
p=p->next;
++j;
}
if(!p||j>i){ //第i个元素不存在
return ERROR;
}
e=p->data;
return OK;
}
根据指定数据元素获取该数据所在的位置
/*根据指定数据元素获取该数据所在的位置*/
Lnode * LocateElem_L(LinkList &L,ElemType e){ //查找值为e的元素
p=L->next;
while(p&&p->data!=e){
p=p->next;
}
return p; //若找到,则返回该值的地址,查找失败就返回NULL
}
根据指定数据元素获取该数据的序号
跟上面根据指定数据元素获取该数据所在的位置有点类似,只是多了一个计数器
/*根据指定数据元素获取该数据的序号*/
Lnode * LocateElem_L(LinkList &L,ElemType e){ //查找值为e的元素
p=L->next;
j=1;
while(p&&p->data!=e){
p=p->next;
j++;
}
if(p){
return j;
}
else{
return 0;
}
}
插入
在单链表的第i个结点前插入值为e的结点
/*在单链表的第i个结点前插入值为e的结点*/
//<1>找到a(i-1)的位置p
//<2>生成一个数据域为e的新结点
//<3>插入新结点
//新结点的指针域指向a(i);
//结点a(i-1)的指针域指向新结点
Status ListInsert_L(LinkList &L,int i,ElemType e){
p=L;
j=0;
while(p&&j<i-1){ //找到第i-1个结点
p=p->next;
++j;
}
if(!p||j>i-1){ //第i-1个元素不存在
return ERROR;
}
s=(LinkList)malloc(sizeof(LNode));
s->next=p->next; //新结点的指针域指向a(i);
p->next=s; //结点a(i-1)的指针域指向新结点
return OK;
}
删除
删除第i个结点
/*删除第i个结点*/
//<1>找到a(i-1)的位置p,(如需必要保存结点i的值)
//<2>令p->next指向a(i+1)
//<3>释放a(i)的空间
Status ListDelete_L(LinkList &L,int i,ElemType &e){
p=L;
j=0;
while(p&&j<i-1){ //找到第i-1个结点
p=p->next;
++j;
}
if(!p||j>i-1){ //第i-1个元素不存在
return ERROR;
}
q=(LinkList)malloc(sizeof(LNode));
q=p->next; //结点i
p->next=q->next; //令p->next指向a(i+1)
e=q->data; //保存结点i的值
free q;
return OK;
}
//查找:因为线性链表只能顺序存取,所以要从头查找,时间复杂度为O(n)
//插入,删除:因为线性链表不用移动元素,只用修改指针,一般情况下时间复杂度为O(1),但是要在单链表中进行,要从头找到相应的前驱结点,时间复杂度为O(n)
单链表的建立
头插法建立单链表
/*头插法建立单链表*/
//<1>从一个空表开始,重复读入数据
//<2>生成新的节点,将读入的数据放在结点的数据域中
//<3>从最后一个结点开始依次将各结点插入到链表前端
void CreateList_H(LinkList &L,int i){ //i为结点个数
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL; //建立一个空表
for(int i=0;i<n;i++){
p=(LinkList)malloc(sizeof(LNode));
p->data=读取数据元素;
p->next=L->next; //链表的插入
L->next=p;
}
尾插法建立单链表
/*尾插法建立单链表*/
//<1>从一个空表开始,将新的结点依次插入到链表尾部,尾指针r指向尾节点
//<2>开始时L与r均指向头结点,每个数据元素申请一个新结点,r指向新结点
void CreateList_R(LinkList &L,int i){
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
LinkList r;
r=L;
for(int i=0;i<n;i++){
p=(LinkList)malloc(sizeof(LNode));
p->data=读取数据元素;
p->next=NULL;
r->next=p; //插到表尾
r=p; //指向新结点
}
}