循环链表的基本操作 C语言

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

typedef struct List
{
    int  data;
    struct List *next;
}list,*p_list;
 
void creat_list(list **p) //如果链表为空,则创建一个链表,指针域指向自己,否则寻找尾节点,将
{                         //将尾节点的指针域指向这个新节点,新节点的指针域指向头结点
    int item;
    list *temp;
    list *target;
    printf("输入节点的值,输入0结束\n");
    while(1)
    {
        scanf("%d",&item);
        if(item==0)return;
 
        if(*p==NULL)   //如果输入的链表是空。则创建一个新的节点,使其next指针指向自己  (*head)->next=*head;
        {
            *p=(list *)malloc(sizeof(list));
            if(!*p)exit(0);
            (*p)->data=item;
            (*p)->next=*p;
        }
        else        //输入的链表不是空的,寻找链表的尾节点,使尾节点的next=新节点。新节点的next指向头节点
        {
            for(target=*p;target->next!=*p;target=target->next);//寻找尾节点
 
            temp=(list *)malloc(sizeof(list));
            if(!temp)exit(0);
            temp->data=item;
            temp->next=*p;  //新节点指向头节点
            target->next=temp;//尾节点指向新节点
        }
    }
}

//释放内存
int deletlist(list *clist) {
    if(clist == NULL){
        return 0;
    }
    free(clist);
    printf("链表已删除\n");
    return 1;
}

void insert(list **pNode,int place,int num)  //链表的插入
{
    list *temp,*target;
    int i;
    if(place==1)                //如果输入的数字是1,表示要插入头节点。应该特殊处理
    {                        //首先找到尾节点,让后让新节点的next指向头节点,尾节点指向新的头节点,在让头指针指向temp。这要特别注意
        temp=(list *)malloc(sizeof(list));
        if(!temp)exit(0);
        temp->data=num;
        for(target=*pNode;target->next!=*pNode;target=target->next);
        
        temp->next=*pNode;
        target->next=temp;
        *pNode=temp;/特别注意
    }
    
    else            //在其他的地方插入节点。  同样先找到要插入的位置,如果位置超出链表的长度,自动插入队尾。                        tar  new  原来是2
    {                //找到要插入位置的前一个节点target,让target->next=temp,插入节点的前驱指向新节点,新节点指向target->next的地址  1    2   3
        for(i=1,target=*pNode;target->next!=*pNode&&i!=place-1;target=target->next,i++);
        temp=(list *)malloc(sizeof(list));
        temp->data=num;
        
        temp->next=target->next;
        target->next=temp;
    }
 
}
 
void Delete(list **pNode,int place)  //删除操作
{
    list *temp,*target;
    int i;
    temp=*pNode;
    if(temp==NULL)                //首先判断链表是否为空
    {
        printf("这是一个空指针 无法删除\n");
        return;
    }
    if(place==1)        //如果删除的是头节点
    {                //应当特殊处理,找到尾节点,使尾节点的next指向头节点的下一个节点 rear->next=(*head)->next;然后让新节点作为头节点,释放原来的头节点
        for(target=*pNode;target->next!=*pNode;target=target->next);
        temp=*pNode;
        
        *pNode=(*pNode)->next;
        target->next=*pNode;
        free(temp);
    }
    else
    {        //删除其他节点
        for(i=1,target=*pNode;target->next!=*pNode&&i!=place-1;target=target->next,i++); //首先找出尾节点
        if(target->next==*pNode)        //判断要删除的位置是否大于链表长度,若大于链表长度,特殊处理直接删除尾节点
        {
            for(target=*pNode;target->next->next!=*pNode;target=target->next);//找出尾节的前一个节点
            temp=target->next;                                                 //    尾节点的前一个节点直接指向头节点  释放原来的尾节点
            target->next=*pNode;
            printf("数字太大删除尾巴\n");
            free(temp);
        }
        else
        {
            temp=target->next;//  删除普通节点  找到要删除节点的前一个节点target,使target指向要删除节点的下一个节点  转存删除节点地址
            target->next=temp->next;    //  然后释放这个节点
            free(temp);
        }
    }
}
 
int findval(list *pNode,int val) //寻找值
{
    int i=1;
    list *node;
    node=pNode;
    while(node->data!=val&&node->next!=pNode)
    {
        i++;
        node=node->next;
    }
    if(node->next==pNode&&node->data!=val)//尾节点指向头节点就跳出,因此还要检测一次为节点的data
    {
        return -1;
    }
    return i;
}

int findnum(list *pNode, int num)
{
    if(num>=1)
    {
        int i=1;
        list *node;
        node=pNode;
        while(num!=i&&node->next!=pNode)
        {
            i++;
            node=node->next;
        }
        if(node->next==pNode&&num!=i)//尾节点指向头节点就跳出,因此还要检测一次为节点的data
        {
            printf("查找失败\n");
            return 0;
        }
        printf("找到的值为%d\n",node->data);
        return 1;
    }
    else
    {
        printf("查找失败\n");
        return 0;
    }
}
 
void show(list *p)//遍历,循环链表的遍历最好用do while语句 ,因为头节点就有值
{
    list *temp;
    temp=p;
    do
    {
        printf("%5d",temp->data);
        temp=temp->next;
    }
    while(temp!=p);
 
    printf("\n");
}
int main()
{
    list *head=NULL;
    int place,num;
    creat_list(&head);
    printf("按序输出元素(原始):");
    show(head);
 
    printf("输入要删除的位置:");
    scanf("%d",&place);
    Delete(&head,place);
    show(head);
 
    printf("输入要插入的位置和数据用空格隔开:");
    scanf("%d %d",&place,&num);
    insert(&head,place,num);
    show(head);
 
    printf("输入你想查找的值:");
    scanf("%d",&num);
    place=findval(head,num);
    if(place!=-1)
        printf("找到的值的位置是place=%d\n",place);
    else
        printf("没找到值\n");
    printf("输入你想查找的序号:");
    int n ;
    scanf("%d",&n);
    findnum(head, n);
    deletlist(head);
 
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值