C语言链表实现

链表实现的逻辑

链表,本质是结构体,包含了节点值和后节点指针两个数据(双向链表会有两个节点指针)

struct LIST{
    int data;
    struct LIST* next;
};
//创建了struct LIST结构体

基本操作的代码实现

插入
struct LIST* listInsert(struct LIST *head,int data,int n){//在索引为i的节点插入新节点(初始索引为0)
    struct LIST *temp1=(struct LIST*)malloc(sizeof(struct LIST));//创建新节点
    temp1->data=data;
    temp1->next=NULL;
    if(n==0){//头插入
        temp1->next=head;
        head=temp1;
        return head;
    }
    struct LIST *temp2=head;//遍历到目标节点的前节点
    for(int i=0;i<n-1;i++){
        temp2=temp2->next;
    }
    temp1->next=temp2->next;//新节点指向目标节点
    temp2->next=temp1;//前节点指向新节点
    return head;//更新头节点
}

优化:

int listLength(struct ListNode* head){
    int len=0;
    struct ListNode *temp=head->next;
    while(temp){
        ++len;
        temp=temp->next;
    }
    return len;
}
int addAtIndex(struct ListNode* head, int index, int val){
    int len=listLength(head);//得到链表长度
    if(index>len || index<0){//判断是否超范围
        return 0;
    }
    else{//范围合理
        struct ListNode *prev=head;
        struct ListNode *newnode=(struct ListNode*)malloc(sizeof(struct ListNode));
        newnode->val=val;
        for(int i=0;i<index;i++){
            prev=prev->next;
        }
        newnode->next=prev->next;
        prev->next=newnode;
        return 1;
    }
    return 0;
}
//head->next为头节点
//成功插入返回1,否则返回0
删除
struct LIST* listDelete(struct LIST *head,int target){//删除节点值为target的节点
    if(target==head->data){//只有一个节点
        head=NULL;
        return head;
    }
    struct LIST *temp1=head;
    while((temp1->next)->data!=target){
        temp1=temp1->next;//遍历到目标节点的前节点
    }
    struct LIST *temp2=temp1->next;//temp2为目标节点
    temp1->next=temp2->next;
    temp2->next=NULL;
    return head;
}
打印
void printList(struct LIST *head){//打印链表
    struct LIST *temp=head;
    printf("list is:");
    while(temp!=NULL){//遍历所有节点并打印
        printf("%d ",temp->data);
        temp=temp->next;
    }
    printf("\n");
}
释放空间
void listFree(struct LIST *head){//释放空间
    if(head){
        //递归free空间
        struct LIST *temp=head->next;
        free(head);
        listFree(temp);
    }
}
求长度
int listLength_fir(struct LIST *head){//得到链表长度
    if(head) return listLength(head->next)+1;
    else return 0;
}

int listLength_sec(struct ListNode* head){
    int len=0;
    struct ListNode *temp=head->next;
    while(temp){
        ++len;
        temp=temp->next;
    }
    return len;
}
寻找节点
struct LIST* listFind(struct LIST *head,int target){//找到data为target的节点
    struct LIST *temp=head;
    while(temp->data!=target){
        temp=temp->next;//未找到,不断后移节点
    }
    return temp;   
}
反转链表
struct LIST* listReverse(struct LIST *head){//反转链表
    if(!head->next){//一个节点
        return head;
    }
    else if(!(head->next)->next){//两个节点
        (head->next)->next=head;
        head->next=NULL;
        return head;
    }
    struct LIST* temp1=head;//前节点
    struct LIST* temp2=head->next;//中间节点
    struct LIST* temp3=temp2->next;//后节点
    while(temp3!=NULL){//中节点为最后有效节点
        temp2->next=temp1;//中节点指向前节点
        temp1=temp2;//前节点后移
        temp2=temp3;//中节点后移
        temp3=temp3->next;//后节点但后移
    }
    temp2->next=temp1;//最后有效节点处理
    head->next=NULL;//头节点指向NULL
    head=temp2;//头节点变换为尾节点
    return head;//返回新的头节点
}

易错点

每次操作完,必须更新头节点,因为头节点指向内容虽然改变,但是头节点本身地址并没有改变,

除非使用

struct LIST **head_ref;
//创建头节点指针的指针

这样就不需要显式地更新头节点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值