您的位置:首页 > 其它

快速排序、堆排序、归并排序

2016-03-28 12:50 531 查看
常见排序有7种:冒泡排序、希尔排序、插入排序、选择排序、快速排序、堆排序、归并排序。

此处讨论后三种时间复杂度为O(NlogN)的算法。

1,快速排序

一般情况下,快速排序迭代(或递归)次数为logN,每次恒进行N次比较;最差情况下迭代N次;

Partition部分:

int Partion(int a[], int low, int high)
{
int i = low;
int j = high;
int val = a[low];
while (i < j)
{
while (i < j && a[j] >= val) j--;
if (i < j)    // 可能已经有序;
a[i++] = a[j];
while (i < j && a[i] <= val) i++;
if (i < j)
a[j--] = a[i];
}
a[i] = val;
return i;
}
QuickSort部分:(先调用Partition找到pivot对应的实际位置idx,然后分别对左右两部分递归)

void QuickSort(int a[], int low, int high)
{
if (i < j)
{
int idx = Partition(a, low, high);
QuickSort(a, low, idx-1);
QuickSort(a, idx+1, high);
}
}
附上快速排序视觉直观图:



2,归并排序

归并排序和快速排序都是基于分治法(Divide and Conquer);需要注意的是归并排序空间复杂度O(N)。

合并两有序部分MergeArray:

void MergeArray(int a[], int low, int mid, int last, int tmp[])
{
int i = low;
int j = mid+1;
int k = 0;
while (i <= mid && j <= high)
{
if (a[i] <= a[j])
a[k++] = a[i++];
else
a[k++] = a[j++];
}
while (i <= mid)
a[k++] = a[i++];
while (j <= high)
a[k++] = a[j++];
for (i = 0; i < k; i++)
a[low+i] = tmp[i];
}

MergeSort部分:

void Mergesort(int a[], int low, int high, int tmp[])
{
if (low < high)
{
int mid = (low +high) / 2;
MergeSort(a, low, mid, tmp);
MergeSort(a, mid+1, high, tmp);
MergeArray(a, low, mid, high, tmp);
}
}
main函数调用:

int main()
{
int n;
int a
;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
int *p = (int *)malloc(n * sizeof(int));
if (p == 0) return 1;
MergeSort(a, 0, n-1, p);   //调用MergeSort排序
free(p);
return 0;
}
继续附上归并排序视觉直观图:



3,堆排序

作为一种数据结构,此处将堆设为一个类,含有的建堆、插入、删除作为方法封装于类中。

(int 类型的最小堆)


class MinHeap {
public:
MinHeap( int maxSize );//根据最大长度建堆
MinHeap( int arr[], int n);
~MinHeap( ) { delete [] heap; }
const MinHeap& operator=( const MinHeap &R );//重载赋值运算符
int Insert(int x );
int RemoveMin(int x );//移除关键码最小的元素,并赋给x
bool IsEmpty( ) const { return CurrentSize == 0; }
int IsFull( ) const { return CurrentSize == MaxHeapSize; }
void MakeEmpty( ) { CurrentSize = 0; }//使堆空
private:
enum { DefaultSize = 50 };//默认堆的大小
int *heap;
int CurrentSize;
int MaxHeapSize;
void FilterDown ( int i, int m ); //自上向下调整堆
void FilterUp ( int i );          //自下向上调整堆
};
MinHeap::MinHeap ( int maxSize )
{
MaxHeapSize = (DefaultSize < maxSize ) ? maxSize : DefaultSize;
heap = new int[MaxHeapSize];
CurrentSize = 0;
}
MinHeap::MinHeap (int arr[], int n )
{
MaxHeapSize = DefaultSize < n ? n : DefaultSize;
heap = new int[MaxHeapSize];
if(heap==NULL){cerr <<"fail" <<endl;exit(1);}
for(int i =0; i< n; i++)
heap[i] = arr[i];               //数组传送
CurrentSize = n;       //当前堆大小
int currentPos = (CurrentSize-2)/2;   //最后非叶
while ( currentPos >= 0 )
{
FilterDown ( currentPos, CurrentSize-1 );
currentPos-- ;
}
}
void MinHeap::FilterDown (int start,int EndOfHeap )
{
int i = start,   j = 2*i+1;           // j 是 i 的左子女
int temp = heap[i];
while ( j <= EndOfHeap )
{
if ( j < EndOfHeap && heap[j] > heap[j+1] )
j++;  //两子女中选小者
if ( temp<= heap[j] ) break;
else { heap[i] = heap[j];  i = j;   j = 2*j+1; }
}
heap[i] = temp;
}
int MinHeap::Insert (int x )
{
if ( CurrentSize == MaxHeapSize )       //堆满
{
cout << "堆已满" << endl;
return 0;
}
heap[CurrentSize] = x;
FilterUp (CurrentSize);          //向上调整为堆
CurrentSize++;
return 1;
}
void MinHeap::FilterUp (int start )
{
int j = start;
int i = (j-1) / 2;
int temp = head[start];
while (i < 0)
{
if (head[i] < temp) break;
else
{
head[j] = head[i];
j = i;
i = (i-1) / 2;
}
}
head[j] = temp;
}
int MinHeap::RemoveMin(int x)
{
if(CurrentSize == 0)
{
cout << "栈已空" << endl;
return 1;
}
x = heap[0];
heap[0] = heap[CurrentSize - 1];
CurrentSize--;
FilterDown(0, CurrentSize-1);
return 0;
}
对数组排序即是调用MinHeap的含参构造函数MinHeap(int arr[], int n),过程为arr[]先对heap[]赋值,然后从第一个分支节点(CurrentSize-2)/2 到根节点进行FilterDown,时间复杂度O(NlogN);

Insert操作:将待插入元素x存入heap[CurrentSize], 从CurrentSize向上进行1次FilterUp,时间复杂度O(logN);

Remove操作:删除根元素(最小值),将heap[0]与heap[CurrentSize-1]对调,从根节点向下进行1次FilterDown, 时间复杂度O(logN);

文章内容由http://www.nowamagic.net/librarys/veda/detail/294 、 http://blog.csdn.net/morewindows/article/details/6709644 整理得到!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: