C 带头节点双向链表快排

#include <stdio.h>
#include <stdlib.h>
#define NAME_LEN 30
#define PASSWD_LEN 30

typedef struct student_data
{
    char name[NAME_LEN];
    char password[PASSWD_LEN];
    int number;
    float math_score;
    float chinese_score;
    float english_score;
}Student_data;

typedef struct student_node
{
    Student_data data;
    struct student_node* previous;
    struct student_node* next;
}Student_node;

struct _school
{
    Student_node* student_head;
    Student_node* student_tail;
};
typedef struct _school School;


void create_list(School* school)
{
    for (int i = 0; i < 20; i++)
    {
        Student_node* temp = (Student_node*)malloc(sizeof(Student_node));
        temp->data.number = rand() % 80;


        if (school->student_head == NULL)
        {
            school->student_head = temp;
            school->student_tail = temp;
            temp->next = NULL;
            temp->previous = NULL;
        }
        else
        {
            temp->previous = NULL;
            temp->next = school->student_head;
            school->student_head->previous = temp;
            school->student_head = temp;
        }
    }

}

void show_list(School* school)
{
    Student_node* temp = school->student_head;
    while (temp)
    {
        printf("|%d| ", temp->data.number);
        temp = temp->next;
    }
    printf("\n---over--\n");
}

Student_node* find_pos_by_number(Student_node* head, Student_node* tail)
{
    if (head == tail)
    {
        return head;
    }
    Student_node* key = head;
    head->previous->next = head->next;
    head->next->previous = head->previous;
    head = head->next;//先移除头节点,指针后移

    while (head != tail)
    {
        while (head != tail && tail->data.number >= key->data.number)
        {
            tail = tail->previous;
        }
        if (head == tail)
        {
            break;
        }

        Student_node* tag = tail->previous;//标记要移除节点前一个节点

        tail->previous->next = tail->next;
        tail->next->previous = tail->previous;  //移除tail 保持链表连续

        tail->previous = head->previous;
        tail->next = head;
        head->previous->next = tail;
        head->previous = tail;//将尾节点插入在头节点位置前

        tail = tag;//恢复尾节点;

        while (head != tail && head->data.number <= key->data.number)
        {
            head = head->next;
        }
        if (head == tail)
        {
            break;
        }

        tag = head->next;//标记要移除节点后一个节点

        head->previous->next = head->next;
        head->next->previous = head->previous;//移除head 保持链表连续

        head->next = tail->next;
        head->previous = tail;
        tail->next->previous = head;
        tail->next = head;//将头节点插入在尾节点位置后

        head = tag;//恢复头节点;
    }
    if (key->data.number > head->data.number)//插入到head后面
    {
        key->previous = head;
        key->next = head->next;
        head->next->previous = key;
        head->next = key;
    }
    else
    {
        key->previous = head->previous;
        key->next = head;
        head->previous->next = key;
        head->previous = key;
    }
    return key;
}


void quick_sort_by_number(Student_node* head, Student_node* tail)
{
    Student_node* before_head = head->previous;//排序完成后这个next就是真实的头
    Student_node* after_tail = tail->next;

    if (head != tail && head->data.number != -99 && tail->data.number != -99)
    {
        Student_node* pos = find_pos_by_number(head, tail);
        if (pos->previous != before_head)
        {
            quick_sort_by_number(before_head->next, pos->previous);
        }
        if (pos->next != after_tail)
        {
            quick_sort_by_number(pos->next, after_tail->previous);
        }
    }
}

void student_sort_by_number(School* school, Student_node* head, Student_node* tail)
{

    Student_node* fake_head = (Student_node*)malloc(sizeof(Student_node));
    Student_node* fake_tail = (Student_node*)malloc(sizeof(Student_node));

    fake_head->data.number = -99;
    fake_tail->data.number = -99;


    fake_head->next = school->student_head;
    school->student_head->previous = fake_head;
    school->student_head = fake_head;

    fake_tail->previous = school->student_tail;
    school->student_tail->next = fake_tail;
    school->student_tail = fake_tail;//两个假节点,放在头尾,不用去处理例外情况;

    quick_sort_by_number(head, tail);
    school->student_head = fake_head->next;
    school->student_head->previous = NULL;
    school->student_tail = fake_tail->previous;
    school->student_tail->next = NULL;
    free(fake_head);
    free(fake_tail);
}

int main(void)
{
    School* school = (School*)malloc(sizeof(School));
    school->student_head = NULL;
    school->student_tail = NULL;
    create_list(school);
    show_list(school);
    student_sort_by_number(school, school->student_head, school->student_tail);
    show_list(school);
}

我自己也觉得这个代码很肿, 但不使用内存拷贝的方法的话, 我只能写成这个样子了. 我就是想用一种其他的方法. 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值