单链表的快排实现

来源:互联网 发布:js截取到某个字符 编辑:程序博客网 时间:2024/05/22 10:25

题目:对单链表,实现快速排序

思路:(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;}


原创粉丝点击