对于排序,相信大家都不陌生,对于数组来说,我们基本能熟练应用许多排序,像冒泡,选择,快排等等。对于链表的排序,在上学期做课程设计的时候忽略了这个问题,然后在最近才进行了实际的操作,结果发现问题还挺多的,实际解决起来学到了一些东西,决定给大家分享一下。
排序的代码
首先,给大家先把链表排序的代码附上,随后我会说明其中运行的过程,还有我当初写的时候,碰到的问题。
void buttle_sort(node *arr[], int number)
{
int i, j;
node *phead;
node *temp, *loop;
node *q;
for(i = 0; i < number; i++)
{
phead = arr[i];
if(phead -> next == NULL || phead == NULL)
{
return ;
}
for(j = 0; j <= (phead -> count); j++) //对多项式进行冒泡排序
{
for(q = phead; q -> next -> next != NULL; q = q -> next)
{
if(q->next->expn > q->next->next->expn)
{
temp = q -> next;
loop = q -> next -> next;
q -> next = loop;
temp -> next = loop -> next;
loop -> next = temp;
}
}
}
}
}
上面的程序是我当时写多项式运算器所用到的,大家对于排序部分只需要看内部的两重循环,也就是我注释的那一部分。
到底怎么排
- 对于链表的冒泡排序,思想并不复杂,它和对数组的冒泡排序其实本质上是一样的,有一些人之所以没有写出来,我相信大部分同学都是对于排序过程中需要互换的两个结点的过程没有写出来。
- 其实,思路很简单:
首先,我们需要设置三个指针:在程序中,我分别设置了*q, *temp, *loop三个指向结点的指针。
我设置的链表是具有头结点的,所以,我们先用q指向 链表的头部,然后用temp,loop分别记录下q结点之后的两个结点,也就是可能需要进行交换的两个结点。
如果,这个结点确实需要交换,那么很简单:
q -> next = loop;
temp -> next = loop -> next;
loop -> next = temp;
简单的两个结点互换位置,人人都会的操作。
就这样,我们很容易就实现了链表的冒泡排序。
我当初遇到的问题
在我第一次进行链表的冒泡排序的时候,写之前感觉思路是非常简单的,就是将数组型的冒泡排序模板放在那,然后把它进行改写,称为链表适用的就行。但是第一次写下来的时候,我的程序直接是不能运行的。随后,我发现了这样几个问题:
- 结点交换的时候,交换发生混乱。(交换后的链表存在节点丢失的情况)
其实,发生这种状况,并不是我们的排序有问题,而是我们记录结点的方式,还有交换的过程可能出现问题。- 段错误。(一般是内存溢出或访问越界的情况)
我觉得重点是这个q -> next -> next != NULL,我们常常因为思考不严谨而出现q -> next != NULL这种情况,这时,对于loop变量来说,他的访问就越界了,因为在链表排序中,我们不能像数组那样只是简单的引入第三变量就可以交换两个位置的值。在链表中,我们需要知道三个结点的位置才能实现两个结点位置的交换,这样就会解决第一种错误发生的情况,保证交换结点的过程中,链表不会混乱。