数据结构学习笔记(六) 排序方法:冒泡 插入 选择 快速

 冒泡排序:
所有相邻两个元素比较,若左边>左边,则交换

若本轮发生了交换,则重复上一步

O(N^2)

#include <iostream>
#include <algorithm>
using namespace std;
void sort(int *a,int n)
{
	bool changed = false;
	do
	{
		changed = false;
		for(int i =1; i <= n; i++)
		{
			if(a[i-1] > a[i])
			{
				swap(a[i-1],a[i]);
				changed = true;
			}
		}
		--n;// 优化:每轮都把最大的排到最后了,所以每次循环时都可以少比较一次
	}while(changed);
}

插入排序


第二个数据开始,循环到最后一个数为止:
(从把每个数据插入适当位置)
1 找适当位置:和左边的数比较,直到左边的数据不比它大或左边没位置
2 插入在找到的位置

这两步有重复的地方 所以在比较时顺便移位
插入法比冒泡法要快很多  因为冒泡里面有大量的交换操作(交换要3步 移动只要1步)
但两者时间复杂度是一样的  O(N^2)
如果只有少量乱序时 冒泡法很快

 void sort( int *a,int n )
 {
	  int j;//因为循环完毕后还要用到j
	 for( int i=1;i <n; i++ ) //从第二个开始 a[1] 
	 {
		 int t = a[i]; //保存要插入的数据
		 for(j= i; j>0 && t<a[j-1] ; j-- ) //和左边的比较 如果这个数比左边的小 将左边的右移一位 
		 {
			 a[j] = a[j-1]; //右移
		}
		a[j] = t;  
	}
}



 选择法:
第i次在未序数据中找最小的元素,跟第1个未序数据(第i个数据)交换。 
每次只做一次交换,所以比插入和冒泡都要快  复杂度O(N^2)
#include <algorithm>
using namespace std;
void sort(int *a,int n)
{
	int min;
	int j;
	for(int i=0;i<n-1;i++) //只做n-1次循环 因为最后一个肯定是最大的
	{
			min = i;
			for( j =i; j<n;j++)
			{
					if(a[j] < a[min])
					{
						min = j;
					}
			}
			
			swap(a[i],a[min]);
	}
}

 快速排序:

O(NlgN)

元素个数不超过一个时直接完成:
1 找分界值(找中间的值,再将它换到最左边)
2 其余的数分组(将其余数分成小于分界值和不小于分界值的两组)
3 小的组最右边的值(此时R指向这个值)和分界值交换位置
4 对分界值左右的两组再排序(递归)


分组方法:

如果L < R(L在R左边)
L从左向右找比分界值不小的  停下来
R从右向左找比分界值小的 停下来

如果L<R,交换 L R指向的数值 

代码学习要点:

1 向左向右查找时要防止越界

2 指针的比较 指针的减法

#include <algorithm>
using namespace std;
void sort(int *a,int n)
{
	
	if(n <=1) return;
	if(n==2) 
	{
		if(a[0] > a[1])
		{
			swap(a[0],a[1]);
		}
		return;
	}
	
	//3个以上才用快排
	int jie = a[n/2]; //选取中间的做分界值
	swap(a[0],a[n/2]);  //将分界值调换到左边来
	int *L = a+1,*R = a+n-1;
	while(L < R)
	{
		//从左向右走
		while(*L < jie && L<R) //谨防L越界 先移L ,R是界
		{
			++L;
		}
		
		//从左向右走
		while(*R >= jie && R >a) //谨防R越界 边界是a
		{
			--R;
		}
		
		if(L < R)
		{
			swap(*L,*R);
		}
	}
	
	if(*R < jie)
	{
		swap(*R,a[0]);
	}
	
	sort(a,R-a);
	sort(R+1,n-1-(R-a));
}


你可能感兴趣的:(数据结构学习笔记(六) 排序方法:冒泡 插入 选择 快速)