带头结点的非循环单项链表的排序

对于链表中数据节点的排序,指的是按照数据域中的某一属性进行排序运算。可以是顺序插入排序实现,在有序的序列中,插入需要排序的元素。

基础代码:

/* 结点数据类型的构造 */
typedef int data_t;
 
/* 整个结点数据类型: */
typedef struct node {
    data_t data;        /* 当前结点数据域:存储当前结点的数据 */
    struct node *next;            /* 当前结点指针域:存储下一个结点空间的起始地址 */
} node_t;
 
 
/* 链表的初始化 */
node_t *CreateLinkList(void)
{
    node_t *head;
 
    /* 开辟头结点存储空间 */
    head = malloc(sizeof(node_t));
    if (head == NULL)
        return head;
    
    memset(head, 0, sizeof(node_t)); //memset函数功能:将指针变量s所指向的前n个字节的内存单元用一个“整数”c替换,可以为任何数据类型的数据进行初始化。
    head->next = NULL;    /* 设置头结点指针域为NULL,表示没有后继结点 */
 
    return head;
}



/* 链表的排序 */
void SortLinkList(node_t *head)
{
    node_t *p;
    node_t *q;
    node_t *r;
    /* 判断链表是否为空表:空表直接结束 */
    if (head->next == NULL)
        return;
    
    p = head->next->next;        /* 第0个有效数据结点作为有效序列,从第1个有效数据结点开始做顺序插入排序 */
    head->next->next = NULL;
    /* 从第1个结点开始循环遍历,并做顺序插入 */    
    while(p != NULL) {
        q = p;            /* 遍历需要排序的结点p赋值给运算结点q */
        p = p->next;    /* 遍历到下一个结点 */
 
        /* 循环找到需要插入结点位置的前一个结点 */
        r = head;
        while(r->next != NULL) {        /* r的下一个结点是否存在,r->next == NULL说明r为有效链表的最后一个结点 */
            if (r->next->data > q->data)    /* 下一个结点数据 > 大于插入结点的数据,说明当前结点为插入结点大的前一个结点 */
                break;
            r = r->next;    
        }
        /* 在r结点后插入待排序结点q */
        q->next = r->next;
        r->next = q;
    }
}

图形解释:

假设最开始是一个带头结点,有4个结点的链表

node_t *p;

node_t *q;

node_t *r; 

if (head->next == NULL)

        return;        

p = head->next->next;

head->next->next = NULL;

定义了三个指针p、q、r;p = head->next->next 这条语句表示p指针指向第2个结点,head->next->next = NULL 然后把第二个结点的指针域置为NULL,q、r指针暂时还没有指向。

  while(p != NULL)

{
        q = p; 
        p = p->next;
        r = head;
        while(r->next != NULL)

       {
            if (r->next->data > q->data) 
                break;
            r = r->next;    
        }
        q->next = r->next;
        r->next = q;

}

第一次进入第一个while,由于p不为空,进入循环

q = p;         q指针指向第2个结点
p = p->next;        p指针指向第3个结点
r = head;         r指针指向头结点

 第一次进入第二个while,由于r->next不为空,进入循环。

if (r->next->data > q->data)         第1个结点的数据大于第2个结点的数据,执行break,跳出第二个while循环。

q->next = r->next;        q指针指向的第2个结点的指针域指向r指针指向的下一个结点,也就是第1个结点
 r->next = q;        r指针指向的头结点的指针域指向q指针指向的第2个结点

第二次进入第一个while,由于p不为空,进入循环

q = p;         q指针指向第3个结点
p = p->next;        p指针指向第4个结点,也就是尾结点
r = head;         r指针指向头结点

 

第二次进入第二个while,由于r->next不为空,进入循环。

if (r->next->data > q->data)         第2个结点的数据大于第3个结点的数据,执行break,跳出第二个while循环。

q->next = r->next;        q指针指向的第3个结点的指针域指向r指针指向的下一个结点,也就是第2个结点
 r->next = q;        r指针指向的头结点的指针域指向q指针指向的第3个结点

 

第三次进入第一个while,由于p不为空,进入循环

q = p;         q指针指向第4个结点,也就是尾结点
p = p->next;        p指针指向NULL
r = head;         r指针指向头结点

第三次进入第二个while,由于r->next不为空,进入循环。

if (r->next->data > q->data)         第3个结点的数据小于第4个结点的数据,执行r = r->next 语句,然后继续进行循环,最后经过第3个结点,第2个结点,最后到第1个结点,然后判断 r->next 的时候为NULL,则不在进入第二个while循环,直接执行后面的两条语句

q->next = r->next;        q指针指向的第4个结点的指针域指向r指针指向的第1个结点的下一个结点,因为为NULL,所以q->next = NULL;
 r->next = q;        r指针指向的第1个结点的指针域指向q指针指向的第4个结点

最后p为空,则跳出循环,程序执行完毕。最后就实现了带头结点的非循环单项链表的排序,采用的是升序排列。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值