单向循环链表及带头指针的链表;

0 阅读2分钟

带头指针的链表;

带头指针的链表和带头节点的链表

一般情况下:我们对带头指针的链表进行操作需要ifelse来判断这个要操作的节点的前一个是否是头指针;采用转换的方法可以有效的避免这个ifelse的问题;

  • 区别:就是一个是以指针当中链表表头一个是以节点当中链表表头;
  • 如何转换:添加一个临时的节点作为链表的表头;(这个临时的节点是放在栈上的)
  • 很多操作和带头节点的链表基本相同;

两个重要的点:

  • 1 如何添加临时节点作为头节点;
  • 2 对函数进行一定的优化;

要用到的英文 intiChainList;初始化表头; destroyChainList;销毁链表; insertChainListHeard;头插头; insertChainListPos;任意位置插入; deleteChainListElement;任意位置删除节点; showChainList;展示节点;

对函数的优化

image.png 其实就是把

while(p->next){
    if(p->next->val == val){
        break;
    }
    p = p->next;
}
while(p->next && p->next->val == val){
    p = p->next;
}

这两个东西其实是等价的,都是在p->next != NULL的条件下,当p->next == val 的时候我们就退出这个循环; 我们可以根据第一个改写出第二个;并且前后的顺序不能改变;

我对于一个指针传入一个函数的见解,

Frist

void text(int *p){
    *p = 30;
}

int main(){
    int a = 10;
    int *p = &a;
    text(p);
    printf("%d",a);
    return 0;
}

屏幕截图 2025-06-29 191807.png

Second

void text(int **p1, int *a2){
    //使p1指向a2;
    *p1 = a2;
}

int main(){

    int a1 = 10;
    int a2 = 30;
    int *p1 = &a1;
    int *p2 = &a2;
    text(&p1,&a2);
    printf("p1 = %d\n",*p1);
    
    return 0;
}

image.png

Third

其实我们这个代码就用到了大量的关于指针的函数;

核心:只能修改这个地址空间里面的东西,但是不能修改这块地址空间;

单向循环链表;

思考:这两段代码有什么不同

while(p->next){
    p = p->next;
}
while(p){
    p = p->next;
}

代码1 一般用于寻找你要修改的节点的前一个节点,通常用于(节点插入/删除)等操作;

代码2 就是节点的遍历工作,它一般不依靠于当前节点的前一个节点,可用于查找等操作;

单向循环链表;

1带头节点的单向循环链表;

image.png

2 带头指针的单向循环链表;

image.png

两者有细微的差别 就是在尾节点的指向不一样,尾节点的指向必须是一个节点;所以带头指针的尾节点和带头节点的尾节点它们的节点next指向不一样;

要用到的英文;

list 表; link 链; loop 循环;

LookNode;

LookLinkList;

intiLookLinkList;

insertLookLinkListHeard;

insertLookLinkListRear;

showLookLinkList;