题目:对单链表,实现快速排序
思路:(2017.9.17增加)其实对比快排的经典实现,改进的地方主要有两个:1、是从一个方向处理切分的,维系两个指针,一个指针quick用于遍历,一个指针slow用于记录,已经处理过的,所有小于枢轴的最后一个值。那么小于等于slow位置的元素都小于枢轴;在slow和quick之间的元素都大于枢轴,quick后面的元素还未处理。一旦quick指向的元素小于枢轴,那么slow++(其指向的值肯定不小于枢轴),与quick交换。2、区间的最后一个元素不处理。
思路(升序):快速排序的主要操作是用选取的枢轴作为切割的基准,左侧所有元素均小于枢轴,右侧均不小于枢轴。经典实现是从头和尾两个方向进行处理,由于单链表的移动方向是单向的,所以必须寻求其他方式。
用一个指针遍历链表,遇到小于枢轴的元素,就将其移到链表的开始处,剩下的就是不小于枢轴的元素;为了实现上述目标,建立两个指针,一个指针指向所有元素都小于枢轴的子链表,一个指针用于遍历。
注意:
1、枢轴一定要放到中间位置,不能放到起始点,也就是循环退出后,要进行一次交换。
2、切分的最后一个元素是不参与处理的。可以看到,经典实现若枢轴位置为 par,那么用的是par-1,par+1。由于单链表不能往前回溯,这个版本实现最后元素不处理,所以用的是par,par+1,可以实现相同的效果。
#include <iostream>
#include<vector>
using namespace std;
typedef struct node
{
node *next;
int data;
node() :next(NULL), data(0){}
}node,*list;
void swap(int &a,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
node *change(vector<int> &a)
{
node *list = new node();
node *temp;
node *tail = list;
for (int i = 0; i < a.size(); i++)
{
temp = new node();
temp->data = a[i];
tail->next = temp;
tail = temp;
}
return list;
}
node *partation(node *low, node *hi)
{
int key = low->data;
node *pslow = low;
node *pquick = low->next;
while (pquick != hi)
{
if (pquick->data < key)
{
pslow = pslow->next;
swap(pslow->data, pquick->data);
}
pquick = pquick->next;
}
swap(pslow->data, low->data);
return pslow;
}
void quicksort(node *low,node *hi)
{
if (low == hi) return;
node *par = partation(low, hi);
quicksort(low, par); //因为最后一个元素不处理
quicksort(par->next, hi);
}
void sort(list lis)
{
quicksort(lis->next,NULL);
}
void listprint(list lis)
{
node *p = lis->next;
while(p)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int main()
{
vector<int> data = {9,3,7,5,8};
list lis = change(data);
sort(lis);
listprint(lis);
system("pause");
return 0;
}