链表

遍历链表,代码如下:

void transverse(node *p)
{
    int n = 0;
    while (p!=NULL)
    {
        printf("node%d value is %d\n", n, p->item);
        n++;
        p = p->next;
    }
}
View Code

代码思想是从链表头开始,只要结点指针p所指向的结点不是空结点,就输出p所指向结点的内容,然后将p指针往后移一个结点。

 

链表升序排序,代码如下:

node* sort_link_list(node *p)
{
    node *ndp = p;
    node *ndpp = p;
    node *head = p;
    int num = 0;
    while (ndp != NULL)//1、获得链表结点个数
    {
        printf("node%d value is %d\n", num, ndp->item);
        ndp = ndp->next;
        num++;
    }
    for (int i = 0; i < num - 1; i++)
    {
        ndp = head;
        ndpp = head;
        for (int j = 0; j < num - 1 - i; j++)
        {
            if (ndp->item>ndp->next->item)
            {
                if (j == 0)
                {
                    head = ndp->next;
                    ndpp = ndp->next;
                }
                node* temp;
                temp = ndp->next->next; //2、交换两个结点在链表中的位置
                ndpp->next = ndp->next;
                ndpp = ndpp->next;
                ndp->next->next = ndp;
                ndp->next = temp;
            }
            else
            {
                ndp = ndp->next;
                if (j != 0)
                {
                    ndpp = ndpp->next;
                }
            }
        }
    }
    return head;
}
View Code

这段代码用的排序算法是冒泡排序法。对链表结点进行排序,相对于数组排序要复杂得多,因为对数组可以直接访问其中的任何一个元素,而链表想要找到其中任何位置的结点都必须得从链表头开始,遍历该结点前所有链表结点一直到所要查找位置的结点。但是不管怎样,归根结底算法的思想都是冒泡排序,即每次对比相邻的两个结点的大小,大的结点往右移,小的往左移。第一次循环找到最大的结点,将其移到了链表的最右(最末尾),第二次循环找到第二大的结点,将其移到链表最右往回一个结点的位置,一直到最后一次循环,找到最小的结点,将其移到链表的最左的位置。

假设现在链表如下:

1

链表有6个结点,首结点数据是2。在只有链表头的情况下,首先我得知道链表里有几个结点,所以我得遍历一遍链表。知道链表结点个数后,就可以知道需要循环几次才能完成排序。根据冒泡法,外层循环次数是num-1次,即5次;内层循环是num-1-i。进入for循环,ndp为指向当前结点的指针,ndpp为指向当前结点的前一个结点的指针,在初始时两者都初始化为指向链表头,如下所示。

2

第一次外循环,i=0。进入内循环,j=0。首先对比第一个结点与第二个结点,2小于6,ndp指向下一个结点,即6,ndpp不变,仍然指向2。指针指向如下:

 

3

第二轮内循环,j=1,ndp指向第二个结点,6>4,第二个结点的值大于第三个结点的值(ndp->item>ndp->next->item),故需要交换第二个结点和第三个结点,交换的思想大致是将第一个结点的next指针指向第三个结点,将第三个结点next指针指向第二个结点,将第二个指针结点指向第四个结点,如下所示。

4

变化一下,上面的图实际如下。

 

5

可以看到,虽然只是调整两个结点的位置,但是需要对三个结点的next进行操作,这也是为什么程序里需要有ndpp指针,因为ndp指针指向当前结点(值为6),但是交换结点需要用到当前结点的上一个结点(值为2)的next指针,因此需要一个ndpp指针指向当前结点的前一个结点。交换结点过程具体如下,回到图3,首先保存第四个结点的地址到一个暂存变量temp,temp = ndp->next->next。

 

6

将第一个结点(值为2)的next指针指向第三个结点,ndpp->next = ndp->next。此时链表变成这样:

 

7

然后将ndpp往后移一个位置,ndpp = ndpp->next,指向第二个结点,虽然此时值为6的结点的next指针尚未改变,但是此时第二个结点应该是值为4的那个结点了。

 

8

再将值为4的结点的next指针指向值为6的结点,ndp->next->next = ndp。

 

9

最后将值为6结点的next指针指向值为3的结点,ndp->next = temp;这样就完成值为6和值为4两个结点在链表位置的交换,同时ndp指针和ndpp指针在链表位置均往后移了一位。

 

10

对上图进行整理,链表此时如下:

 

11

后面的交换都是类似的操作,就不细述了。

 

对链表倒序输出,代码如下:

void reverse(node *p)
{
    if (p == NULL)
        return;
    else
    {
        reverse(p->next);
    }
    printf("%d\n",p->item);
}
View Code

代码思想是利用递归法,一直搜索到链表尾,然后返回,一路输出结点的值。

 

输出链表倒数第n个结点的值,代码如下:

void backward_n(node *p, int n)
{
    int num = 0, i = 1;
    node *head = p;
    while (p != NULL)
    {
        num++;
        p = p->next;
    }
    p = head;
    while (i < num - n + 1)
    {
        i++;
        p = p->next;
    }
    printf("backward n node value is %d\n", p->item);
}
View Code

代码思想为先计算链表有几个结点,假设有N个结点,那么倒数第n个结点就是顺数第N-n+1个结点,所以只要重新从链表头开始,搜索到第N-n+1个结点,输出其值即可。

 

主函数如下:

#include <stdio.h>

typedef struct NODE{
    int item;
    struct NODE *next;
}node;

node nd1, nd2, nd3, nd4, nd5, nd6, nd7;
void main()
{
    nd1.item = 10;
    nd2.item = 8;
    nd3.item = 6;
    nd4.item = 5;
    nd5.item = 4;
    nd6.item = 3;
    nd7.item = 2;
    nd1.next = &nd2;
    nd2.next = &nd3;
    nd3.next = &nd4;
    nd4.next = &nd5;
    nd5.next = &nd6;
    nd6.next = &nd7;
    nd7.next = NULL;
    node *ndp = &nd1;
    node *ndpp = &nd1;
    node *head = ndp;

    head = sort_link_list(head);
    transverse(head);
    //reverse(&nd1);

}
View Code

 

转载于:https://www.cnblogs.com/yangyuke/p/9893050.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值