交换排序
这次学习了两种交换排序算法:冒泡排序和快速排序算法;两种方法都是基于元素交换的概念而来的,交换排序的基本思想是:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。下面简单介绍其基本原理。
1、冒泡排序
基本原理:把序列的每个元素当成一个气泡,则轻的气泡在上,重的在下。排序过程为每次从最下面的气泡R[n]开始,让它与上一个气泡R[n-1]比较大小
若比上面的小,则交换顺序,否则不改变。然后进行下一步,对R[n-1]和R[n-2]进行相同的比较,直到R[1]和R[0],这样一趟比较就将序列中最小的额
元素放在了序列的最上面,然后进行第二趟比较,从R[n]到R[1],将第二小的元素放在R[1]位置,依次类推,最后就可以得到排列的序列
演示动画:http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/maopaopaixu.htm
算法为就地排序,是稳定的,由于元素移动次序多,因此性能比直接插入排序要差
2、快速排序
基本原理:采用分治的思想,将问题分成若干个结构相同的问题通过递归来解决。假设一个序列R,i,j作为上下边界,在R中取一个值作为分界点,把R中的值分成两边,左边的比R小,右边的比R大,这样再分别对左右两边的值做相同的运算,最终就可以得到排列好的序列。
演示动画:http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/kuaisupaixu.htm
排序是非稳定的
下面来看具体实现:
#include <iostream>
#include <vector>
using namespace std;
const int N = 20; //定义常量 也可以这样 #define N 20
void disp(vector<int> vec); //输出函数,
void bubble(vector<int> &vec,int n); //冒泡算法
void quicksock(vector<int> &vec, int l, int r); //快速排序
int partition(vector<int> &vec,int l, int r); //快速算法---->划分函数
int main()
{
vector<int> vec1(N),vec2;
int a[N] = {2 ,19 ,3 ,25 ,4 ,0,8,22,10,2,9,45,12,16,21,41,6,18,34,10};
for(int i = 0; i < N; i++)
{
vec1[i] = a[i];
}
vec2 = vec1;
disp(vec1); //排序前序列1
disp(vec2); //排序前序列2
bubble(vec1,N); //冒泡排序
quicksock(vec2,0,N-1); //快速排序
disp(vec1); //排序后序列1
disp(vec2); //排序后序列2
return 0;
}
void disp(vector<int> vec) //输出函数
{
cout << "排列顺序为:";
for(int i = 0; i < N; i++)
{
cout << vec[i] << " ";
}
cout << endl;
}
void bubble(vector<int> &vec,int n)
{
int flag,temp;
for(int i = 0; i < n; i++)
{
flag = 0;
//作为标记,看这一趟有没有进行交换,若没有则不再需要交换,直接退出循环
for(int j = n-1; j >=i+1; j--) //注意j的范围
{
if(vec[j] < vec[j-1])
{
temp = vec[j];
vec[j] = vec[j-1];
vec[j-1] = temp;
flag = 1;
}
}
if(!flag) //这一趟没进行交换
return ; //直接跳出方法
}
}
void quicksock(vector<int> &vec, int l, int r)
{
int pivotpos; //划分后基准(分届点)位置
if(l<r)
{
pivotpos = partition(vec,l,r); //划分
quicksock(vec,l,pivotpos-1); //对基准左边的序列递归排序
quicksock(vec,pivotpos+1,r); //对基准右边的序列递归排序
}
}
int partition(vector<int> &vec,int l, int r)
{
int temp;
int pivot = vec[l]; //第一个数作为基准,需与每次运算区间相关,不能是总的序列的一个固定值,只能固定位于区间相对位置
while(l<r)
{
while (l<r && vec[r] >= pivot) //过滤掉大于基准的值
r--;
if(l<r && vec[r] < pivot) //找到第一个小于基准的值,并交换
{
temp = vec[l]; //若是基准为序列第一个数的话不用交换,直接赋值就行,因为第一个值保存在pivot中不会丢失
vec[l] = vec[r];
vec[r] = temp;
l++;
}
while(l<r && vec[l] <= pivot) //过滤掉小于基准的值
l++;
if(l<r && vec[l] > pivot) //找到大于基准的值,交换放到基准右边
{
temp = vec[r];
vec[r] = vec[l];
vec[l] = temp;
r--;
}
}
vec[l] = pivot; //由于上面用的是交换,这里也可以省略,若是用赋值方式则需要将这个值传递过去
return l;
}