插入排序
简介:最简单的插入排序,利用了这样的事实:位置0—P的元素是排序的,后边N-P+1个元素向前面已经
排序的元素中插入,需要嵌套循环,第一层P—N(P的初始值为1,即前一个元素是排序的),第二层1—P,
即第一层每个元素需要跟已经排序的元素比较,进而在合适的位置插入,插入….biubiubiu
效率:由于是嵌套循环,每次都要N次比较,所以效率是(O (N*N))
稳定性:稳定的
看代码:
void InsertSort(int A[], int N)
{
int j = 0;
int P = 0;
for(P = 1; P < N; ++P)
{
// 记录A[P],找到合适位置后,将其插入 biubiubiu
int Tmp = A[P];
// 找到合适位置:如果A[P] 小于前边的值,则将前面已经排序的后移,即挪出来一个位置
for(j = P; j > 0 && A[j-1] > Tmp; --j)
A[j] = A[j-1];
// 在挪出位置上插入Tmp
A[j] = Tmp;
}
}
希尔排序
简介:是冲破二次时间屏障的第一批算法之一,原理:通过比较相距一定间隔的元素工作,各趟比较
所用的距离随着算法的进行而减小,知道只比较相邻元素的最后一趟排序为止—在每个增量上进行一次子
数组插入排序;
效率:O(nlogn)~O(n2),效率依赖增量的设计
稳定性:不稳定;原因:我们知道插入排序是稳定的,但是每个增量上的插入排序可能打乱稳定性
看代码:
void ShellSort(int A[], int N)
{
int i = 0;
int P = 0;
// 首先确定一个增量
int d = N/2;
// 在每个增量上进行插入排序,所以要增加一个循环控制增量的缩小
for(d; d > 0; d /= 2)
{
// 在每个增量上进行一次子数组的插入排序
for(P = d; P < N; ++P)
{
// 记录,以便在合适位置插入
int Tmp = A[P];
// 跟Tmp比较,大于则向后移动,给Tmp挪出位置
for(i = P; i > 0; i -= d)
{
if(A[i-d] > Tmp)
A[i] = A[i-d];
else
break;
}
// 在合适的位置插入
A[i] = Tmp;
}
}
}
快速排序
简介:正如名字,实践中最快的排序算法;原理:选出一个枢纽元素P,待排序数组前后两个标记i,j,
A[i]向后移动,A[j]向前移动,如果A[i] > P && A[j] < P 则交换i,j,那么一趟排序后,数据被分为两份,前边的都小于枢纽元素,后边的都大于枢纽元素,然后分而治之,分别对前后做相同的处理;
效率:(O(N*logN))
稳定性:不稳定
看代码:
void QuickSort(int A[], int left, int right)
{
int i = 0;
int j = 0;
// 选取枢纽元素,这里就按最简单的,取第一个元素
int q = A[left];
// 记录前后元素
i = left;
j = right;
while(i < j)
{
// 顺序比较重要,要先从后向前
while(i < j && A[j] > q)
--j
while(i < j && A[i] < q)
--i
// 停了,可以交换了
if(i < j)
{
int tmp = A[i];
A[i] = A[j];
A[j] = A[i];
}
}
// 一趟比较结束了,我们枢纽元素还在A[left]位置上
// 可以确定的是A[i] 一定是小于等于枢纽元素的,进行交换,这样
// 枢纽左边都是小于他的元素,右边都是大于他的元素
A[left] = A[i];
A[i] = q;
// 分而治之
QuickSort(A, left, i - 1);
QucikSort(A, i + 1, right);
}
这里有篇文章配图讲的挺形象的:
http://developer.51cto.com/art/201403/430986.htm
快排延伸:
(1)听过这样一个问题,给你一个大数组,炒鸡大(不能借助辅助数组什么的)!有奇数有偶数,
以O(N)时间复杂度,处理以下数据,使得左边都是奇数,右边都是偶数。看完快排很快就能想到解题思路,
即:省去“分治”的快排,具体就是定义两个变量,分别从两个方向同时遍历数据,然后进行数据交换;
(2)实践中,在对少量元素排序时(3 <= N <= 20),插入排序效率要高于快速排序,所以一个改进的方式
是,快排中元素在比较少时,用插入排序;
不行,我还要默写一遍快排,八嘎!
void QuickSort(int A[], int left, int right)
{
int low = left;
int high = right;
int qvoit = A[left]; // 记录枢纽元素
while(low < high)
{
while(low < high && qvoit < A[high])
--high;
while(low < high && qvoit > A[low])
++low;
if(low < high)
{
int tmp = A[low];
A[low] = A[high];
A[high] = tmp;
}
}
A[left] = A[low];
A[low] = tmp;
QuickSort(A, left, low - 1);
QuickSort(A, low + 1, right);
}
// TODO