线性表的链表C语言实现基本操作 代码+注释详解 含头指针&不含头指针【求表长,初始化,插入,删除,遍历】

线性表的链表实现基本操作详解

  1. 求链表表长
  2. 查找元素
  3. 插入元素
  4. 删除元素
  5. 初始化含头指针和不含头指针的链表
  6. 遍历含头指针和不含头指针的链表

注:含头指针(即头指针也携带有效数字)的链表的操作

1. 求链表表长

(1)含头指针

int Length_headvalue( List Ptrl)
{
    List p ;
    p= Ptrl;//P是一个临时的指针,指向链表的头
    int j=0;//计数器
    while (p!=NULL)//while(p)
    {
        p=p->next;
        j++;//当前p指向第j个元素
    }
    return j;
}

(2)不含头指针

int Length( List Ptrl)
{
    List p ;
    p= Ptrl;//P是一个临时的指针,指向链表的头
    int j=-1;//计数器
    while (p!=NULL)//while(p)
    {
        p=p->next;
        j++;//当前p指向第j个元素
    }
    return j;
}

2.查找

①按序号查找
(1)含头指针

(2)不含头指针
②按值查找
(1)含头指针
(2)不含头指针

List FindKth_headvalue(int K,List Ptrl)
{
    List p = Ptrl;
    int i = 1;
    while(p!=NULL && i<K)
    {
        p=p->next;
        i++;
    }
    if(i==K)
      return p;//找到第K项
    else //链表中没有第K项
    return  NULL;
}

(2)不含头指针

List FindKth(int K,List Ptrl)
{
    List p = Ptrl;
    int i = 1;
    while(p!=NULL && i<K+1)
    {
        p=p->next;
        i++;
    }
    if(i==K+1)
      return p;//找到第K项
    else //链表中没有第K项
    return  NULL;
}

②按值查找

(1)含头指针

List FindValue_headvalue(int X,List Ptrl)
{
    List p=Ptrl;
    while(p!=NULL &&p->Data!=X)
    {
        p=p->next;//指针往后挪的基本操作
    }
    return p;//此时也有两种情况,但无论找到的或没找都返回NULL
   /* if(p->Data==X)
      return p;
    else
     return NULL;*///若是没找到,此时p==NULL;所以都可以等效返回NULL;  
}

(2)不含头指针

List FindValue(int X,List Ptrl)
{
    List p=Ptrl->next;
    while(p!=NULL &&p->Data!=X)
    {
        p=p->next;//指针往后挪的基本操作
    }
    return p;//此时也有两种情况,但无论找到的或没找都返回NULL
   /* if(p->Data==X)
      return p;
    else
     return NULL;*///若是没找到,此时p==NULL;所以都可以等效返回NULL;  
}

3.插入

在这里插入图片描述
在第i-1个结点后插入一个值为X的新节点
插入时关键在于插入的前一个结点是什么!这样才能把新节点接上去
步骤(1)先malloc一块空间,用S指向
步骤(2)再找到链表的第i-1个结点,用P指向
所以如果X插在表头,则需单独考虑。

(1)含头结点

List Insert_headvalue(ElementType X,int i,List Ptrl)
{
    List p,s;//p是用于指向原来链表第i-1个元素,s是用来装新结点
    if(i==1)//此时没有第i-1个元素,所以用不到p
    {
        s=(List)malloc(sizeof(struct LNode));
        s->Data=X;//显然头指针是含了数值的
        s->next=Ptrl;
        return s;//注意这里返回的是新链表表头
    }
    p=FindKth_headvalue(i-1,Ptrl);//只有待插位置之前有结点,才能用此函数找,,因为没有第0位置
    if(p==NULL)
      printf("参数错误");
    else
    {
        s=(List)malloc(sizeof(struct LNode));
        s->Data=X;
        s->next=p->next;
        p->next=s;//关键语句,千万不能调换顺序
        return Ptrl;
    }
}

(2)不含头节点

List Insert(ElementType X,int i,List Ptrl)
{
    List p,s;//p是用于指向原来链表第i-1个元素,s是用来装新结点
    if(i==1)//此时没有第i-1个元素,所以用不到p
    {
        s=(List)malloc(sizeof(struct LNode));
        s->Data=X;
        s->next=Ptrl->next;
        Ptrl->next=s;
        return Ptrl;//注意这里返回的是原链表表头
    }
    p=FindKth(i-1,Ptrl);//只有待插位置之前有结点,才能用此函数找,,因为没有第0位置
    if(p==NULL)
      printf("参数错误");
    else
    {
        s=(List)malloc(sizeof(struct LNode));
        s->Data=X;
        s->next=p->next;
        p->next=s;//关键语句,千万不能调换顺序
        return Ptrl;
    }
}

4.删除

在这里插入图片描述
(1)含头节点

List delete_headvalue (int i,List Ptrl)//删除第i个位置上的结点,同样要找到第i-1个结点
{
    List p,s;
    if(i==1)
    {
        s=Ptrl;
        if(Ptrl!=NULL)
          Ptrl=Ptrl->next;
        else //此链表为空,无法删除结点,也没有结点需要free
        free(s);//一定要记得free,否则会内存泄漏
        return Ptrl;      
    }
    /*if(i==1)
    {
        return Ptrl->next;
    }*/
    //上面这样写存在两种隐患,一是链表有可能是空的,所以Ptrl->next可能出问题,
    //二是没有free可能内存泄漏
    else 
    {
        p=FindKth_headvalue(i-1, Ptrl);//此时要找的是待删除结点的前一个结点
        if (p==NULL)//这个结点有可能找不到
        {
            printf("参数错误");
            return NULL;
        }
        else if(p->next==NULL)//此时有可能待删除结点的位置是NULL,也无效
        {
            printf("第%d个结点不存在",i);
            return NULL;//函数在每种情况下都要对应有返回值!
        }
        else
        {
            s=p->next;
            p->next=s->next;
            free(s);//这三句关键语句顺序也不能调换!!!
            return Ptrl;
        }
        
        /*
        else
        {不能这样写!这样会无法free待删除结点
            p->next=p->next->next;
        }*/
    }
}

(2)不含头节点

List delete(int i,List Ptrl)//删除第i个位置上的结点,同样要找到第i-1个结点
{
    List p,s;
    if(i==1)
    {
        s=Ptrl->next;
        if(s!=NULL)
          Ptrl->next=s->next;
        else //此链表为空,无法删除结点,也没有结点需要free
        free(s);//一定要记得free,否则会内存泄漏
        return Ptrl;      
    }
    /*if(i==1)
    {
        return Ptrl->next;
    }*/
    //上面这样写存在两种隐患,一是链表有可能是空的,所以Ptrl->next可能出问题,
    //二是没有free可能内存泄漏
    else 
    {
        p=FindKth(i-1, Ptrl);//此时要找的是待删除结点的前一个结点
        if (p==NULL)//这个结点有可能找不到
        {
            printf("参数错误");
            return NULL;
        }
        else if(p->next==NULL)//此时有可能待删除结点的位置是NULL,也无效
        {
            printf("第%d个结点不存在",i);
            return NULL;//函数在每种情况下都要对应有返回值!
        }
        else
        {
            s=p->next;
            p->next=s->next;
            free(s);//这三句关键语句顺序也不能调换!!!
            return Ptrl;
        }
        
        /*
        else
        {不能这样写!这样会无法free待删除结点
            p->next=p->next->next;
        }*/
    }
}

5.初始化链表

给出链表的结点个数,建立链表

(1)含头指针

List gen_headvalue( int n)//创建有n个结点的链表
{
    List head ,node,end;
    int num;
    head=(List)malloc(sizeof(struct LNode));
    end=head;
    int i;
    for(i=0;i<n;i++)
    {
        scanf("%d",&num);
        if(i==0)
        {
            head->Data=num;
        }
        else
        {
        node=(List)malloc(sizeof(struct LNode));
        node->Data=num;
        end->next=node;
        end=node;
           
        }
    }
    end->next=NULL;

    return head;
}

(2)不含头指针

List gen( int n)//创建有n个结点的链表
{
    List head ,node,end;
    int num;
    head=(List)malloc(sizeof(struct LNode));
    end=head;
    int i;
    for(i=0;i<n;i++)
    {
        scanf("%d",&num);
        node=(List)malloc(sizeof(struct LNode));
        node->Data=num;
        end->next=node;
        end=node;
    }
    end->next=NULL;

    return head;
}

6.遍历链表

(1)含头指针

void display_headvalue(List Ptrl)
{
    while(Ptrl!=NULL)
    {
        if(Ptrl->next==NULL)
        {      
            printf("%d",Ptrl->Data);
            Ptrl= Ptrl->next; 
        }
        else
        {
        printf("%d ",Ptrl->Data);
        Ptrl= Ptrl->next;      
        }
       
    }
}

(2)不含头指针

void display(List Ptrl)
{
    while(Ptrl->next!=NULL)
    {
        if(Ptrl->next->next==NULL)
        {      
            Ptrl= Ptrl->next;
            printf("%d",Ptrl->Data);
        }
        else
        {
        Ptrl= Ptrl->next;
        printf("%d ",Ptrl->Data);
        }
       
    }
}

这里再推荐另一篇相关博文~
线性表的数组实现基本操作 代码+注释详解

猜你喜欢

转载自blog.csdn.net/qq_45955041/article/details/106952706