上一篇总结了简单的排序算法,这一篇继续。。。
堆排序
思想
堆,堆顶元素(即第一个元素)必为最小项(小顶堆)(升序序列)或者最大项(大顶堆)(降序序列)。若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的。虽然说是一棵完全二叉树,但不是说就得根据这些数据还需要重新建立数据结构,对于一维数组有这样的规定:
根节点i与左右孩子的下标的关系是:
左孩子:i*2+1
右孩子:i*2+2
每一个孩子节点对应的双亲节点的下标是:(i-1)/ 2
通过如上的关系,就可以将一维数组当做是一个二叉树来处理了。
实现
void adjustHeap(int*arr,int begin,int len);
//堆的初始化
void heap_init(int *arr,int len)
{
for (int i=len-1;i >=0;i--)
{
adjustHeap(arr,i,len);
}
}
//堆的调整
void adjustHeap(int*arr,int begin,int len)
{
int tmp = arr[begin];
int child = 2*begin+1;//左孩子的下标
while (child < len)
{
if (child+1 < len && arr[child] < arr[child+1])
//如果右孩子大于左孩子,就调整到右孩子的下标
{
++child;
}
if (arr[begin] < arr[child])//如果较大的子节点大于父节点,
//那么子节点就替换它的父节点
{
arr[begin] = arr[child];
begin = child;
child = 2*begin+1;
}
else//如果当前节点大于它的左右孩子,就不需要调整,直接退出
{
break;
}
arr[begin] = tmp;//将待调整的节点的值放到比它还大的孩子节点的位置上
}
}
void heap_sort(int *arr,int len)
{
if (arr == NULL || len < 1)
{
return;
}
cout<<"heap_sort"<<endl;
//堆的初始化
heap_init(arr,len);
//从最后一个元素开始对序列进行调整
for (int i=len-1;i >=0;i--)
{
//交换堆顶元素
int top = arr[i];
arr[i] = arr[0];
arr[0] = top;
adjustHeap(arr,0,i);
}
}
效率
堆排序也是属于选择排序的一种,但是它的效率是很高的,和快速排序不相伯仲,时间复杂度都是O(nlogn)。
快速排序
思想
1.在待排序的元素任取一个元素作为基准(通常是选取第一个元素,但最好的选择方法是从待排序的元素中随机选取一个作为基准),称为基准元素
2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比它小的放在它的左边;
3.对左右两个分区重复以上的步骤直到所有的元素都是有序的。
递归实现
int patition(int *arr,int l,int r)
{
int tmp = arr[l];
while (l < r)
{
while (arr[r] >= tmp && l < r)
{
r--;
}
arr[l] = arr[r];
while (arr[l] <=tmp && l < r)
{
l++;
}
arr[r] = arr[l];
}
arr[l] = tmp;
return l;
}
void quick(int *array,int start,int end)
{
if (start < end)
{
int pos = patition(array,start,end);
quick(array,0,pos-1);
quick(array,pos+1,end);
}
}
void quick_sort(int*array,int num)
{
if (array == NULL || num < 1)
{
return;
}
cout<<"quick sort"<<endl;
quick(array,0,num-1);
}
非递归实现
void quick_sortRecursion(int*arr,int len)
{
if (arr == NULL || len < 1)
{
return;
}
stack<int>st;
int left = 0;
int right = len-1;
st.push(left);
st.push(right);
while (!st.empty())
{
right = st.top();
st.pop();
left = st.top();
st.pop();
if (left < right)
{
int pos = patition(arr,left,right);
st.push(left);
st.push(pos);
st.push(pos+1);
st.push(right);
}
}
}
效率
和堆排序一样的,都是属于选择排序,而且效率都是O(nlogn)。
现在就理解这么多,还有个效率更高的归并排序,后面再说吧,关于排序算法中的其他几个,见
http://blog.csdn.net/adminlpx/article/details/79279750这也是我的总结。继续加油!^_^