人人范文网 范文大全

C++ 八种排序算法总结及实现

发布时间:2020-03-02 03:00:46 来源:范文大全 收藏本文 下载本文 手机版

八种排序算法总结之C++版本

五种简单排序算法

一、冒泡排序

【稳定的】

void BubbleSort( int* a,int Count ) //实现从小到大的最终结果 { int temp; for(int i=1; i

for(int j=Count-1; j>=i; j--)

if( a[j]

{

temp = a[j];

a[j] = a[j-1];

a[j-1] = temp;

} }

现在注意,我们给出O方法的定义:

若存在一常量K和起点n0,使当n>=n0时,有f(n)

现在我们来看1/2*(n-1)*n,当K=1/2,n0=1,g(n)=n*n时,1/2*(n-1)*n

二、交换排序

【稳定的】

void ExchangeSort( int *a,int Count) { int temp; for(int i=0; i

for(int j=i+1; j

if( a[j]

{

temp = a[j];

a[j] = a[i];

a[i] = temp;

} }

时间复杂度为O(n*n)。

三、选择法

【不稳定的】

void SelectSort( int *a,int Count) { int temp; //一个存储值

int pos; //一个存储下标

for(int i=0; i

temp = a[i];

pos = i;

for(int j=i+1; j

if( a[j]

{

temp = a[j];

pos = j; //下标的交换赋值,记录当前最小元素的下标位置

}

a[pos] = a[i];

a[i] = temp; } }

遗憾的是算法需要的循环次数依然是1/2*(n-1)*n。所以算法复杂度为O(n*n)。

我们来看他的交换。由于每次外层循环只产生一次交换(只有一个最小值)。所以f(n)

四、插入法

【稳定的】

void InsertSort( int *a,int Count) { int temp; //一个存储值

int pos; //一个存储下标

for(int i=1; i

{

temp = a[i]; //当前要插入的元素

pos = i-1;

while( pos>=0 && temp

{

a[pos+1] = a[pos]; //将前一个元素后移一位

pos--;

}

a[pos+1] = temp; } }

其复杂度仍为O(n*n)。

最终,我个人认为,在简单排序算法中,直接插入排序是最好的。

五、希尔排序法

【不稳定的】 /* * 希尔排序,n为数组的个数 */ void ShellSort( int arr[], int n ) { int temp,pos; int d = n; //增量初值

do{

d = d/3 + 1 ;

for(int i= d; i

{

temp = arr[i];

pos = i-d;

while( pos>=0 && temp

arr[ pos + d ] = arr[pos];

pos -= d;

}

arr[ pos + d ] = temp;

} } while( d > 1 ); }

//实现增量为d的插入排序

三种高级排序算法

一、快速排序

辅助空间复杂度为O(1)

【不稳定的】 void QuickSort( int *a,int left, int right) { int i,j,middle,temp; i = left; j = right; middle = a[ (left+right)/2 ]; do {

while( a[i]

i++;

while( a[j]>middle && j>left ) //从右扫描小于中值的数

j--;

if( i

{

temp = a[i];

a[i] = a[j];

}

a[j] = temp;

i++;

j--; }

} while ( ii),递归右半边 if( i

注意,在扫描过程中,对于给定参考值,对于向右(左)扫描,如果扫描值大(小)于或等于参考值,就需要进行交换。最终得到的结果是,j左边的值都小于参考值,而i右边的值都大于参考值,j和i之间的值都等于参考值。对j左边和i右边的分别使用递归,就可以完成最终的排序。

这里我没有给出行为的分析,因为这个很简单,我们直接来分析算法:首先我们考虑最理想的情况

1.数组的大小是2的幂,这样分下去始终可以被2整除。假设为2的k次方,即k=log2(n)。

2.每次我们选择的值刚好是中间值,这样,数组才可以被等分。

第一层递归,循环n次,第二层循环2*(n/2)......

所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n 所以算法复杂度为O(log2(n)*n)

其他的情况只会比这种情况差,最差的情况是每次选择到的middle都是最小值或最大值,那么他将变

成交换法(由于使用了递归,情况更糟),但是糟糕的情况只会持续一个流程,到下一个流程的时候就很可能已经避开了该中间的最大和最小值,因为数组下标变化了,于是中间值不在是那个最大或者最小值。但是你认为这种情况发生的几率有多大??呵呵,你完全不必担心这个问题。实践证明,大多数的情况,快速排序总是最好的。

如果你担心这个问题,你可以使用堆排序,这是一种稳定的O(log2(n)*n)算法,但是通常情况下速度要慢

于快速排序(因为要重组堆)。

二、归并排序(两种实现方法均要掌握)

【稳定的】

归并排序是一种极好的外部排序方法,即针对数据保存在磁盘上而不是高速内存中的问题。

//以下程序参考数据结构课本P286页的模板,为使用指针链表实现的 #include using namespace std;

struct node{ //链表的节点数据

int value; node *next; };

node * divide_from( node * head ) { node * position, * midpoint, * second_half; if( (midpoint=head) == NULL ) //List is empty

return NULL; position = midpoint->next; while( position != NULL ) //Move position twice for midpoint\'s one move {

position = position->next;

if( position != NULL )

{

midpoint = midpoint->next;

position = position->next;

}

} second_half = midpoint->next; midpoint->next = NULL; //在这里将原链拆断,分为两段

return second_half; }

node * merge( node * first, node * second) { node * last_sorted; //当前已经链接好的有序链中的最后一个节点

node combined; //哑节点

last_sorted = &combined; while( first!=NULL && second!=NULL ) {

if( first->value value ) {

last_sorted->next = first;

last_sorted = first;

first = first->next;

}else {

last_sorted->next = second;

last_sorted = second;

second = second->next;

} } if( first==NULL )

last_sorted->next = second; else

last_sorted->next = first; return combined.next; //返回哑节点的后继指针,即为合并后的链表的头指针 }

//这里的参数必须是引用调用,需要这个指引去允许函数修改调用自变量 void MergeSort( node * &head) { if( head != NULL && head->next != NULL ) //如果只有一个元素,则不需排序 {

node * second_half = divide_from( head );

MergeSort( head );

MergeSort( second_half );

head = merge( head, second_half ); } }

int main() { node a,b,c,d; node *p1, *p2, *p3, *p4,*head; p1 = &a; p2 = &b; p3 = &c; p4 = &d; a.value = 2; b.value = 4; c.value = 3; d.value = 1; a.next = p2; b.next = p3; c.next = p4; d.next = NULL; //调用归并排序前的结果

head = p1; while( head != NULL ) {

coutvalue

head = head->next; } cout

head = p1; while( head != NULL ) {

coutvalue

head = head->next; } cout

//以下程序为使用数组实现的归并排序,辅助空间复杂度为O(n)

#include using namespace std;

void Merge( int data[], int left, int mid, int right ) { int n1,n2,k,i,j; n1 = midmid; int *L = new int[n1]; //两个指针指向两个动态数组的首地址

int *R = new int[n2]; for( i=0,k=left; i

L[i] = data[k]; for( i=0,k=mid+1; i

R[i] = data[k]; for( k=left,i=0,j=0; i

if( L[i]

data[k] = L[i];

i++;

} else {

data[k] = R[j];

j++;

} } if( i

for( j=i; j

} /* * left:数组的开始下标,一般为0;right:数组的结束下标,一般为 (n-1) */

void MergeSort( int data[], int left, int right ) { if( left

int mid = left + ( right-left ) / 2; //mid=(right+left)/2,防止溢出

MergeSort( data, left, mid );

MergeSort( data , mid+1, right );

Merge( data , left, mid , right ); } }

int main() { int data[] = {9,8,7,2,5,6,3,55,1}; //排序前的输出

for(int i=0; i

cout

for(int i=0; i

cout

三、堆排序 【不稳定的】

/* * 向堆中插入current元素的函数 */ void insert_heap( int data[], const int ¤t, int low, int high )

data[k] = L[j]; else //if( j

for( i=j; i

data[k] = R[i]; delete []L; //回收内存 delete []R; { int large; //元素data[low]左右儿子中,大者的位置

large = 2*low + 1; while( large

if( large

large++;

if( current > data[ large ] ) //待插入元素的值比它的两个儿子都大

break;

else {

data[ low ] = data[ large ]; //将其左右儿子的大者上移

low = large;

large = 2 * large + 1;

} } data[ low ] = current; } /* * 建立堆函数,num为数组data的元素个数

* 只有一个结点的自动满足堆的属性,因此不必担心树中的任何树叶,即 * 不必担心表的后一半中的元素。如果从表的中间点开始并从后向前工作,就 * 能够使用函数insert_heap去将每个元素插入到包含了所有后面元素的部分堆 * 中,从而创建完整的堆。 */ void build_heap( int data[], int num ) {

int current; for( int low = num/2 - 1; low>=0; low-- ) {

current = data[ low ];

insert_heap( data, current, low, num-1 ); } } /* * 堆排序主函数,num为数组data的元素个数 */ void heap_sort( int data[], int num ) { int current, last_sorted; build_heap( data, num ); //建立堆

for( last_sorted = num-1; last_sorted>0; last_sorted-- ) { //逐个元素处理

current = data[ last_sorted ]; //data[0]在整个数组排序结束前,存储的是待排序元素中最大的元素

data[last_sorted] = data[0];

insert_heap( data, current, 0, last_sorted-1 ); } } int main() { //用于排序算法的输入输出

int a[8] = {5,7,1,2,9,4,6,3,}; for(int i=0; i

cout

for(int i=0; i

cout

排序算法总结

10种排序算法总结

用php实现的各种排序算法总结

操作系统课程设计实验报告用C++实现银行家算法

《算法导论》学习总结——快速排序

51CTO下载排序和算法总结

排序算法教学反思

4.4排序算法设计

各种排序算法的优缺点

C++ m的n次方算法代码

C++ 八种排序算法总结及实现
《C++ 八种排序算法总结及实现.doc》
将本文的Word文档下载到电脑,方便编辑。
推荐度:
点击下载文档
点击下载本文文档