#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);
}
我自己也觉得这个代码很肿, 但不使用内存拷贝的方法的话, 我只能写成这个样子了. 我就是想用一种其他的方法.