算法和数据结构-链表

本文详细介绍了如何在C语言中使用结构体和指针实现无头和有头链表的插入、删除、查找以及链表的销毁和输出功能,包括示例代码和函数实现。
摘要由CSDN通过智能技术生成

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

typedef struct Node
{
    int data;//数据区 
    struct Node* next;//指针区域 
}Node;

Node* getnewnode(int val)//开辟链表的存储空间 
{
    Node *p=(Node*)malloc(sizeof(Node));
    p->data=val;
    p->next=NULL;
    return p;

Node *NOheadinsert(Node *head,int val,int pos)//无头链表的插入 
{
    if(pos==0){
        Node *p=getnewnode(val);
        p->next=head;
        return p;
    }
    Node *p=head;
    for(int i=1;i<pos;i++){
        p=p->next;
    }
    Node *node=getnewnode(val);
    node->next=p->next;
    p->next=node;
    return head;    
}

Node *YESheadinsert(Node *head,int val,int pos)//有头链表的插入 
{
    Node virtualhead,*p=&virtualhead;//构造虚拟头节点,*p地址初始化为虚拟头节点的地址,virtualhead是一个真实的节点,不是指针 
    virtualhead.next=head;
    for(int i=0;i<pos;i++){
        p=p->next;
    }
    Node *node=getnewnode(val);
    node->next=p->next;
    p->next=node;
    return virtualhead.next; 
}

Node *Noheadremove(Node *head,int target)//删除链表的无头操作 
{
     // 处理头节点是目标节点的情况
     if (head && head->data == target) {
        Node* temp = head;
        head = head->next;
        free(temp);
        return head;
    }
     // 遍历链表找到目标节点
    Node *cur=head;
    Node *ptr=NULL;
    while(cur&&cur->data!=target){
        ptr=cur;
        cur=cur->next;
    } 
     // 如果目标节点不存在于链表中
    if(!cur) return head;
    //跳过当前节点 
    ptr->next=cur->next;
    free(cur);
    return head;
}

Node *Yesheadremove(Node *head,int target)//删除链表的有头操作 
{
      //首先,需要找到要删除的目标节点。遍历链表,从头节点开始,逐个比较节点的值,直到找到目标节点或者遍历到链表末尾
      Node virtualhead,*p=&virtualhead;
      virtualhead.next=head;
      Node *ptr=NULL; 
      while(p&&p->data!=target){
            ptr=p;
          p=p->next;
      }
      if(!p) return virtualhead.next;//目标节点不存在于链表当中 
      //找到目标节点后,需要修改前一个节点的指针,将其指向目标节点的下一个节点,跳过目标节点,现在的ptr就是当前指针的前一个节点指针 
      ptr=ptr->next->next;//向后走两步跳过要删除的节点
      // 删除目标节点
      // prev->next = p->next;这样跳过也可以要删除的下一个节点赋值给待删除的上一个节点 ,相当于next走了两步进行删除 
      return virtualhead.next; 
}

int search(Node *head,int val)//查找链表中指定元素的值 
{
    Node *p=head;
    while(p){
        if(p->data==val) return 1;
        p=p->next;
    }
    return 0;
}

void clear(Node *head)//销毁链表 
{
    if(head->next==NULL)return ;
    for(Node *p=head,*q;p;p=q){
        q=p->next;
        free(p); 
    }
    return ;
}

void output(Node *head)//输出链表 
{
    int len=0,n=0;
    for(Node *p=head;p;p=p->next){
        n+=1;
    }
    for(int i=0;i<n;i++){
        printf("%3d",i);
        printf("  ");
    }
    printf("\n");
    for(Node *p=head;p;p=p->next){
        printf("%3d",p->data);
        printf("->");
    }
    printf("\n\n\n");
    return ;
}

int main(void)
{
    srand(time(0));
    #define max 10
    Node *head=NULL;
    for(int i=0;i<max;i++){
        int pos=rand()%(i+1),val=rand()%100;
        printf("insert %d at %d to linklist\n",val,pos);
        head=NOheadinsert(head,pos,val);
        output(head); 
    }
    clear(head);
    return 0;
}

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值