单链表的查找(带头结点)
按位查找(GetElem(L,i))
获取表L 中第i 个位置的元素的值(带头结点),可把头结点看成第0 个结点,程序代码如下:
LNode *GetElem(LinkList L,int i){
if(i<0)
return null;
LNode *p; //定义指针p 指向当前扫描到的结点
int j=0; //当前p 指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点,是不存数据的
while(p!=NULL&&j<i){
p=p->next;
j++;
}
return p;
}
看了上面的代码片段,我们是不是感觉很熟悉呢?是的,它于我们在前面的在第 i 个位置插入元素e (带头结点)的代码是一样的,只不过这里是找第i 个结点,而前面循环找的是第 i-1 个结点。
按值查找(LocateElem(L,e))
找到数据域==e 的结点,部分程序代码片段如下:
LNode * LocateElem(LinkList L,ElemType e){
LNode *p=L->next;
//从第1个结点开始查找数据域为e的结点
while(p!=NULL&&p->data!=e)
p=p->next;
return p; //找到结点返回该结点
}
通过上面的启发,我们是不是觉得求一个单链表的长度就很容易了呢?看看下面的代码,你说简不简单?
int Length(LinkList L){
int len=0; //统计表长
LNode *p=L;
while(p->next!=NULL){
p=p->next;
len++;
}
return len;
}
单链表的建立(带头结点)
如果给你很多个数据元素(ElemType),你会把他们存到一个单链表里吗?
-
初始换一个单链表(前面的文章讲过单链表初始化的实现)
-
在其头部或尾部进行插入数据元素。就我的理解,就是对指定结点进行后插操作。
尾插法
结合前面学习的后插操作,我们来实现一下尾插法建立单链表:
LinkList List_Tailnsert(LinkList &l){
int x; //设ElemType为整型
L=(LinkList)malloc(sizeof(LNode)); //建立头结点
LNode *s,*r=L; //r为表尾指针
scanf("%d",&x); //输入结点的值
while(x!=2022){ //输入2022表示结束
s=(LNode *)malloc(sizeof(LNode)); //申请一个结点并把s指向这个结点
s->data=x;
r->next=s;
r=s; //r指向新的表尾结点,即永远保证r 指向最后一个结点
scanf("%d",&x);
}
r->next=NULL; //尾结点指针置空
return L;
}
下面结合动图理解一下上面的几行代码:
头插法
还是刚才说的,我们想一想前面的后插操作 InsertNextNode(LNode *p,ElemType e) 的实现,然后我们再来看一看用头插法建立单链表的实现:
LinkList List_HeadInsert(LinkList &L){
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
L->next=NULL; //初始化空链表,防止指向不安全区域,注意下哦
scanf("%d",&x);
while(x!=2022){
s=(LNode*)malloc(sizeof(LNode)); //创建新结点
s->data=x;
s->next=L->next;
L-next=s; //将新结点插入表中,L 为头指针
scanf("%d",&x);
}
return L;
}
不知道我们发现了没有,头插法建立单链表可以实现单链表的逆置!