• 18 循环链表


    1,循环链表的初始化

     定义一个头结点和尾指针的方式,头结点在这里是用来连接 第一个结点和最后一个结点的结点

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 
     4 typedef struct Link {     
     5     int data;
     6     struct node* next;
     7 }link;
     8 
     9 link* head_node; //声明一个头结点
    10 link* ptail;    //声明一个尾指针
    11 
    12 link* initLink()  //初始化循环链表
    13 {
    14     link* new_node;
    15     head_node = (link*)malloc(sizeof(link));
    16     ptail = head_node; //尾指针指向头结点
    17     
    18     //初始化创建10个结点的循环链表
    19     for (int i = 0; i < 10; i++)
    20     {
    21         link* new_node = (link*)malloc(sizeof(link));
    22         ptail->next = new_node;//把新节点接到链表上去,相当于head_node->next = new_node,但这里不能使用head_node->next,而是使用ptail->next,因为头结点不能动
    23         
    24         new_node->data = i;//给新申请的结点赋值
    25         new_node->next = head_node; //新申请的结点是尾结点,指针域指向头结点,构成尾连接头的单向循环
    26         
    27         ptail = new_node;//尾指针后移指向新节点
    28     }
    29     //printf("头结点中的数据是:%d
    ", head_node->data); //-842150451,头结点中没有值,头结点只是连接第一个结点和尾结点的结点
    30     return  head_node;
    31 }
    32 void showLink(link* headNode)    //输出循环链表的所有元素 
    33 {
    34     link* tmp = headNode->next;//tmp是指针类型,值是头结点的指针域中保存的值,所以tmp指针指向头结点的下一个结点
    35     while (tmp != headNode){ //tmp指针从头结点的下一个结点开始后移,直到指向头结点(此时已经遍历一遍循环链表)
    36         printf(" %d ", tmp->data);//打印出tmp所指向结点的数据,tmp指向某个结点的写法是tmp=node,因此tmp->data,就等于是node->data,tmp->data可以打印出所指向结点的数据
    37         tmp = tmp->next;//tmp指针后移
    38     }
    39     printf("
    ");
    40 }
    41 
    42 
    43 void main()
    44 {
    45     head_node = initLink(); //获取初始化后的头结点
    46     printf("初始化后的链表是:
    ");
    47     showLink(head_node);
    48 }

     2,删除指定位置处的结点

     4 #include<stdio.h>
     5 #include<stdlib.h>
     6 
     7 typedef struct Link {
     8     int data;
     9     struct node* next;
    10 }link;
    11 
    12 link* head_node; //声明一个头结点
    13 link* ptail;    //声明一个尾指针
    14 
    15 link* initLink()  //初始化循环链表
    16 {
    17     link* new_node;
    18     head_node = (link*)malloc(sizeof(link));
    19     ptail = head_node; //尾指针指向头结点
    20 
    21     //初始化创建10个结点的循环链表
    22     for (int i = 0; i < 10; i++)
    23     {
    24         link* new_node = (link*)malloc(sizeof(link));
    25         ptail->next = new_node;//把新节点接到链表上去,相当于head_node->next = new_node,但这里不能使用head_node->next,而是使用ptail->next,因为头结点不能动
    26 
    27         new_node->data = i;//给新申请的结点赋值
    28         new_node->next = head_node; //新申请的结点是尾结点,指针域指向头结点,构成尾连接头的单向循环
    29 
    30         ptail = new_node;//尾指针后移指向新节点
    31     }
    32     //printf("头结点中的数据是:%d
    ", head_node->data); //-842150451,头结点中没有值,头结点只是连接第一个结点和尾结点的结点
    33     return  head_node;
    34 }
    35 
    36 
    37 void showLink(link* headNode)    //输出循环链表的所有元素
    38 {
    39     link* tmp = headNode->next;//tmp是指针类型,值是头结点的指针域中保存的值,所以tmp指针指向头结点的下一个结点
    40     while (tmp != headNode){ //tmp指针从头结点的下一个结点开始后移,直到指向头结点(此时已经遍历一遍循环链表)
    41         printf(" %d ", tmp->data);//打印出tmp所指向结点的数据,tmp指向某个结点的写法是tmp=node,因此tmp->data,就等于是node->data,tmp->data可以打印出所指向结点的数据
    42         tmp = tmp->next;//tmp指针后移
    43     }
    44     printf("
    ");
    45 }
    46 
    47 
    48 
    49 //删除位置num处的节点 
    50 void delNode(link* headNode, int num)   
    51 {
    52     link* p, * q; //p,q 是两个link型的指针
    53     p = headNode->next;//把头结点的指针域赋给p,p就指向头结点的下一个结点(第一个结点)
    54     int j = 0; //计数器
    55     while (p != headNode) //p不指向头结点的情况下
    56     {
    57         j++;
    58         p = p->next; //p从指向第一个结点开始后移,while循环遍历一次可以知道表的长度(j的值)
    59     }
    60     if (num<1 || num>j) // 删除的结点是大于等于1,小于等于表长
    61     {
    62         printf("删除位置出错
    ");
    63         return -1;
    64     }
    65 
    66     p = headNode; //p重新指向头结点
    67     link* r;
    68     for (j = 1; j < num; j++) {
    69         p = p->next; 
    70     } //j=num时会结束for循环,此时p指向了第num-1个结点
    71     q = p->next;//q是第num个结点,是p的下一个结点
    72     r = q;
    73     p->next = r->next; //删除q结点后,通过 r 把链表再接回去
    74     free(q);
    75     76 }
    77 
    78 
    79 
    80 void main()
    81 {
    82     head_node = initLink(); //获取初始化后的头结点
    83     printf("初始化后的链表是:
    ");
    84     showLink(head_node);
    85     
    86     printf("删除第四个结点后的链表是:
    ");
    87     delNode(head_node, 4);
    88     showLink(head_node);
    89 
    90 }

    3,查询指定位置处的结点的下一个结点

    #include<stdio.h>
    #include<stdlib.h>
    
    typedef struct Link {
        int data;
        struct node* next;
    }link;
    
    link* head_node; //声明一个头结点
    link* ptail;    //声明一个尾指针
    
    link* initLink()  //初始化循环链表
    {
        link* new_node;
        head_node = (link*)malloc(sizeof(link));
        ptail = head_node; //尾指针指向头结点
    
        //初始化创建10个结点的循环链表
        for (int i = 0; i < 10; i++)
        {
            link* new_node = (link*)malloc(sizeof(link));
            ptail->next = new_node;//把新节点接到链表上去,相当于head_node->next = new_node,但这里不能使用head_node->next,而是使用ptail->next,因为头结点不能动
    
            new_node->data = i;//给新申请的结点赋值
            new_node->next = head_node; //新申请的结点是尾结点,指针域指向头结点,构成尾连接头的单向循环
    
            ptail = new_node;//尾指针后移指向新节点
        }
        //printf("头结点中的数据是:%d
    ", head_node->data); //-842150451,头结点中没有值,头结点只是连接第一个结点和尾结点的结点
        return  head_node;
    }
    
    
    void showLink(link* headNode)    //输出循环链表的所有元素
    {
        link* tmp = headNode->next;//tmp是指针类型,值是头结点的指针域中保存的值,所以tmp指针指向头结点的下一个结点
        while (tmp != headNode){ //tmp指针从头结点的下一个结点开始后移,直到指向头结点(此时已经遍历一遍循环链表)
            printf(" %d ", tmp->data);//打印出tmp所指向结点的数据,tmp指向某个结点的写法是tmp=node,因此tmp->data,就等于是node->data,tmp->data可以打印出所指向结点的数据
            tmp = tmp->next;//tmp指针后移
        }
        printf("
    ");
    }
    
    
    
    //根据数据返回该处的结点
    link* queryNode(link* headNode, int num) {
        link* tmp = headNode->next;
        while (tmp != headNode) {
            if (tmp->data == num) {
                return tmp;
            }
            tmp = tmp->next;
        }
        return NULL;
    }
    
    
    
    
    void main()
    {
        head_node = initLink(); //获取初始化后的头结点
        printf("初始化后的链表是:
    ");
        showLink(head_node);
        
    
        link* node = queryNode(head_node, 4)->next;
        printf("第4个结点的下一个结点是:%d
    ",node->data);
        
    
    }

    4,删除指定位置处的前驱结点

    将 上面删除指定位置结点的方法 改用一些即可

    #include<stdio.h>
    #include<stdlib.h>
    
    typedef struct Link {
        int data;
        struct node* next;
    }link;
    
    link* head_node; //声明一个头结点
    link* ptail;    //声明一个尾指针
    
    link* initLink()  //初始化循环链表
    {
        link* new_node;
        head_node = (link*)malloc(sizeof(link));
        ptail = head_node; //尾指针指向头结点
    
        //初始化创建10个结点的循环链表
        for (int i = 0; i < 10; i++)
        {
            link* new_node = (link*)malloc(sizeof(link));
            ptail->next = new_node;//把新节点接到链表上去,相当于head_node->next = new_node,但这里不能使用head_node->next,而是使用ptail->next,因为头结点不能动
    
            new_node->data = i;//给新申请的结点赋值
            new_node->next = head_node; //新申请的结点是尾结点,指针域指向头结点,构成尾连接头的单向循环
    
            ptail = new_node;//尾指针后移指向新节点
        }
        //printf("头结点中的数据是:%d
    ", head_node->data); //-842150451,头结点中没有值,头结点只是连接第一个结点和尾结点的结点
        return  head_node;
    }
    
    
    void showLink(link* headNode)    //输出循环链表的所有元素
    {
        link* tmp = headNode->next;//tmp是指针类型,值是头结点的指针域中保存的值,所以tmp指针指向头结点的下一个结点
        while (tmp != headNode){ //tmp指针从头结点的下一个结点开始后移,直到指向头结点(此时已经遍历一遍循环链表)
            printf(" %d ", tmp->data);//打印出tmp所指向结点的数据,tmp指向某个结点的写法是tmp=node,因此tmp->data,就等于是node->data,tmp->data可以打印出所指向结点的数据
            tmp = tmp->next;//tmp指针后移
        }
        printf("
    ");
    }
    
    
    
    //删除指定结点处的的前驱结点
    void delPrior(link* headNode, int num) {
        link* p, * q; //p,q 是两个link型的指针
        p = headNode->next;//把头结点的指针域赋给p,p就指向头结点的下一个结点(第一个结点)
        int j = 0; //计数器
        while (p != headNode) //p不指向头结点的情况下
        {
            j++;
            p = p->next; //p从指向第一个结点开始后移,while循环遍历一次可以知道表的长度(j的值)
        }
        if (num<2 || num>j+1) // 删除的结点是大于等于1,小于等于表长
        {
            printf("删除位置出错
    ");
            return -1;
        }
    
        p = headNode; //p重新指向头结点
        link* r;
        for (j = 1; j < num-1; j++) {
            p = p->next;
        } //j=num时会结束for循环,此时p指向了第num-1个结点
        q = p->next;//q是第num个结点,是p的下一个结点
        r = q;
        p->next = r->next; //删除q结点后,通过 r 把链表再接回去
        free(q);
    }
    
    
    void main()
    {
        head_node = initLink(); //获取初始化后的头结点
        printf("初始化后的链表是:
    ");
        showLink(head_node);
        
        
        printf("删除第4个结点的前驱结点后的链表是:
    ");
        delPrior(head_node,4);
        showLink(head_node);
        
    
    }

  • 相关阅读:
    Java实现 蓝桥杯 历届试题 城市建设
    Java实现 蓝桥杯 历届试题 城市建设
    Java实现 蓝桥杯 历届试题 城市建设
    Java实现 蓝桥杯 历届试题 城市建设
    MYSQL创建数据库时候直接指定编码和排序规则
    Eclipse 安装插件(aptana、svn 、git、Java EE、JSHint)
    (转)CentOS无损调整磁盘分区大小的实现方法
    Linux(centos)系统各个目录的作用详解
    Ecplise插件安装方法
    Fedora25 将eclipse的快捷方式添加到Applications中
  • 原文地址:https://www.cnblogs.com/shanlu0000/p/12508249.html
Copyright © 2020-2023  润新知