学习目标:单链表基本操作的代码实现
学习内容:
1、 带头结点的单链表查找第i个元素
LNode * GetElem(LinkList l, int i){
if(i<0){ //防止i为负数
return NULL;
}else{
LNode *p;
int j=0; //计数用,0作为头结点
p = l; //指针来取数据
while(p!=NULL && j<i){ //若i为0,则跳出循环,返回p为头结点
p = p->next;
j++;
}
return p;
}
}
平均时间复杂度为O(n)
2、 带头结点的单链表后插操作
bool InsertNextNode(LNode *p, ElemType e){
if(p==NULL){ //若程序先查找后插入的话,查找函数的返回值若为空,谈何插入
return false;
}else{
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NULL){
return false;
}else{
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
}
}
平均时间复杂度为O(n)
3、带头结点的单链表按位插入
与后插操作不同的是p指针指向第i-1个元素,然后执行后插操作,若插入位置为1,头结点的优势就显现出来了,查询位置的时候将指针s指向头结点就行,(依然是j=0; if(s!=NULL&&j<i-1) j++; return s;)
LNode *InsertNode(LNode *p, ElemType e){
if(p==NULL){
return false;
}else{
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NULL){
return false;
}else{
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
}
}
4、 带头结点的单链表按值查找
LNode * LocateElem(LinkList l, ElemType e){
LNode *p = l->next; //从第一个节点开始查找
while(p!=NULL&& p->data!=e){
p = p->next;
}
return p;
}
平均时间复杂度为O(n)
5、带头结点的单链表求链表长度
int Length(LinkList l){
int len = 0;
LNode *p = l;
while(p->Next != NULL){ //判断从头结点开始
p = p->next;
len++;
}
return len;
}
平均时间复杂度为O(n)
6、指定结点前插操作(不给链表头指针)骚操作:数据域交换
指定结点的删除也可以用这个方法
bool InsertPriorNode(LNode *p, ElemType e){
if(p==NULL){
return false;
}else{
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s==NUll){
return false;
}else{
s->data = e;
s->next = p->next;
p->next = s;
//以上代码都是正常的后插操作
//下面的代码是将后插结点的数据与指定结点的数据交换
s->data = p->data;
p->data = e;
return ture;
}
}
}
7、尾插法建立单链表(带头结点)
bool ListInsert(LinkList &l){
//初始化空表
l = (LNode*)malloc(sizeof(LNode));
l->next = NULL; //最好写上,肯定没错,在头插法中一定要写
LNode *s, *r = l; //①这样写可以减少内存的浪费(s若定义在循环里,则每循环一次就建一个s)②s为新建结点,r指向尾节点
int x;
scanf("%d", &x);
while(x!=999){
s = (LNode*)malloc(LNode);
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL;
return l;
}
8、头插法建立单链表(带头结点)
注:头插法可以解决链表逆序的问题,可以直接在原链表中操作,也可以建新链表
bool ListInsert(LinkList &l){
//初始化空表
l = (LNode*)malloc(sizeof(LNode));
l->next = NULL; //必须写
LNode *s;
int x;
scanf("%d", &x);
while(x!=999){
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next = l->next;
l->next = s;
scanf("%d", &x);
}
return l;
}
9、单链表的逆置
bool nizhiList(LinkList &l){
LNode *p = l->next;
LNode *s, *r = l; //s为新建结点,r为指向释放的结点,不需要尾结点,因为每次插在头结点后面,l就能用
while(p!=NULL){
s = (LNode*)malloc(sizeof(LNode));
if(s==NULL){
return false;
}else{
s->data = p->data; //建新结点存数据
s->next = l->next; //新结点的指向头结点的后一个
l->next = s; //新结点链接头结点
r = p;
p = p->next;
free(r); //释放结点p
}
}
return true;
}
学习时间:
1、2021.5.8 22:30-23:00
2、 2021.5.9 9:30-11:00
学习产出:
1、 数据结构视频2.3.2_2、2.3.2_3
2、单链表基础操作代码书写
3、单链表逆置