今天听同学面友录说道单链表是否可以用快速排序算法,想起自己面百度一面的时候面试官也面到这个问题,由于本人是个小菜鸟,所以花了一个下午的时间整理了一下。
算法思想:对于一个链表,以head节点的值作为key,然后遍历之后的节点,可以得到一个小于key的链表和大于等于key的链表;由此递归可以对两个链表分别进行快速。这里用到了快速排序的思想即经过一趟排序能够将小于key的元素放在一边,将大于等于key的元素放在另一边;
面试回答:如果面试官问快速排序是否适合单链表,答案当然是不适合;但是如果问单链表可不可以用快速排序,答案当然是肯定的;下面贴出一段拙劣的代码,希望大家修正!
code:
struct LinkNode{
int value;
LinkNode* next;
LinkNode(): value(0), next(NULL) {};
};
void Quicksort(LinkNode* &head, LinkNode* &end){
LinkNode *head1, *head2, *end1, *end2; /* 记录每次分割后前后两个链表的头尾节点*/
head1 = head2 = end1 = end2 = NULL;
if( head == NULL ) return; //如果遍历的当前节点为空,返回
LinkNode *p, *pre1, *pre2; /*用于遍历链表将链表中的元素分成大于key和小于key两个部分*/
p = pre1 = pre2 = NULL;
int key = head->value;
p = head->next; head->next = NULL; //将head的值孤立出来
while( p != NULL ) {
//小于key的链表
if ( p->value < key ){
if( !head1 ) { head1 = p; pre1 = p; }
else{ pre1->next = p; pre1 = p; }
p = p->next;
pre1->next = NULL;
}
//大于等于key的链表
else{
if( !head2 ) { head2 = p; pre2 = p; }
else { pre2->next = p; pre2 = p; }
p = p->next;
pre2->next = NULL;
}
}
end1 = pre1; end2 = pre2; /*产生新链表的首尾节点*/
//对左右两个链表进行递归快排
Quicksort(head1, end1);
Quicksort(head2, end2);
//从递归栈返回的时候,将key节点和左右两个链表连起来
//左右链表都存在
if( end1 && head2){
end1->next = head; head->next = head2;
head = head1; end = end2;}
//只有左链表
else if(end1) {
end1->next = head;
end = head; head = head1; }
//只有右链表
else if(head2){
head->next = head2; end = end2;}
}