单链表的排序
因为要编写用单链表实现多项式相加的程序所以要用到单链表的排序,我最开始想的是用一个指针数组储存链表每个结点的地址,然后可以用冒泡排序或选择排序比较结点的数据域然后交换指针数组存储的结点地址,排完序最后遍历一遍数组改变数组存储的对应指针指向的结点的指向关系,最后调试许久,不知问题出在那里;遂换一种思路,利用冒泡排序比较结点储存的指数大小然后编写一个Swap函数交换结点储存的指数和系数,依然无果;最后我选取了我看的博客中一种非常巧妙的方法,在遇到更好的方法前我打算将这个方法形成我的套路。
-
主要思路:
通过改变带头结点的链表指向关系进行排序 -
操作原理:
使用三个指针,p,r,pre,设接受的头指针为t,通过3
个指针的使用修改指向关系 -
操作过程
结点结构体:
typedef struct Polynode{
int index; //指数
double exp; //系数
struct Polynode *next; //指针域
}Polynode;
函数头:
void Sort(Polynode*t)
过程:
(1)Polynode *p=t->next,*pre;
创建结点指针p,使p指向头结点的下一个结点,同时创建结点指针pre
(2)Polynode *r=p->next;
创建结点指针r并初始化指向p指向的下一个结点
(3)p->next=nullptr;
释放p指向的结点的指针域,如果不释放可能使后面步骤中出现一个结点的指针域指向本身
(4)p=r;
使p指向r指向的结点
(5)while(p!=nullptr)
循环条件为p不为空指针,这是为了保证链表末尾的结点也参与比较
(6)r=p->next;
使r指向p的下一个结点,这是为了保证链表不会断开
(7)while(pre->next!=nullptr&&pre->next->index>p->index)
二重循条件为pre的下一个结点不为空结点且pre的下一个结点的指数大于p指向的结点的指数,这是为了确保链表按照指数从大到小排序
(8)pre=pre->next;
如果符合循环条件,
情况一,pre一直移动到下一个结点为空则这时p指向的结点的指数比前面结点的指数都小;
情况二,pre移动到指数比p要小的结点的前一个指数比p要大的结点,此时p指向的结点的指数处于这两个结点的中间;如果不符合循环条件,
情况三,p指向的结点的指数大于pre指向的下一个结点的指数(此时pre指向的是头结点)。
(9)p->next=pre->next;
将pre的指针域传给p,此时要分三种情况;
情况一:p指向的结点的指数比前面的结点都小,此时pre的指针域为空,这种情况下此操作即将p的指针域置空;
情况二:pre移动到指向的下一个结点的指数比p要小的结点,这种情况下此操作使p指向pre指向的结点的下一个结点(即指数比p要小的结点)
情况三:p指向的结点的指数大于前面所有结点的指数,此时pre为头结点,这种情况下此操作即使p指向头结点指向的第一个结点
(10)pre->next=p;
使pre指向的结点的指针指向p,即使p成为pre的下一个结点分三种情况讨论;
情况一:p指向的结点的指数比前面的结点都小,则经过循环pre移动到p的前一个指针且指针域为空,又经过步骤(9)p的指针域被置空,这种情况下此操作使的p成为新链表中指数最小的结点
情况二:pre移动到指向的下一个结点的指数比p要小的结点,
进过步骤(9)使p指向pre指向的结点的下一个结点(即指数比p要小的结点),这种情况下此操作使p插入到pre与pre指向的下一个结点中
情况三:p指向的结点的指数大于前面所有结点的指数,此时pre为头结点,操作(9)使p指向头结点指向的第一个结点,这种情况下使头结点指向p,p成为第一个结点
(10)p=r;
将r指向的结点的地址传给p,使得可以遍历整个链表
- 完整代码
void Sort(Polynode*t){
Polynode *p=t->next,*pre;
Polynode *r=p->next;
p->next=nullptr;
p=r;
while(p!=nullptr){
r=p->next;
pre=t;
while(pre->next!=nullptr&&pre->next->index>p->index){
pre=pre->next;
}
p->next=pre->next;
pre->next=p;
p=r;
}
}