码迷,mamicode.com
首页 > 其他好文 > 详细

18 循环链表

时间:2020-03-17 08:03:38      阅读:50      评论:0      收藏:0      [点我收藏+]

标签:写法   lin   main   创建   image   指针   打印   style   情况下   

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\n", 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("\n");
40 }
41 
42 
43 void main()
44 {
45     head_node = initLink(); //获取初始化后的头结点
46     printf("初始化后的链表是:\n");
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\n", 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("\n");
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("删除位置出错\n");
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("初始化后的链表是:\n");
84     showLink(head_node);
85     
86     printf("删除第四个结点后的链表是:\n");
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\n", 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("\n");
}



//根据数据返回该处的结点
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("初始化后的链表是:\n");
    showLink(head_node);
    

    link* node = queryNode(head_node, 4)->next;
    printf("第4个结点的下一个结点是:%d\n",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\n", 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("\n");
}



//删除指定结点处的的前驱结点
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("删除位置出错\n");
        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("初始化后的链表是:\n");
    showLink(head_node);
    
    
    printf("删除第4个结点的前驱结点后的链表是:\n");
    delPrior(head_node,4);
    showLink(head_node);
    

}

技术图片

 

18 循环链表

标签:写法   lin   main   创建   image   指针   打印   style   情况下   

原文地址:https://www.cnblogs.com/shanlu0000/p/12508249.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!