本文实现了冒泡排序,直接插入排序,直接选择排序,快速排序,堆排序,归并排序,希尔排序其中排序算法,并指出他们的时间复杂度以及稳定性情况。
#include<stdio.h>
void swap(int* a, int* b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
/*
//冒泡排序:每次都将最大值放到要排的序列末尾
//时间复杂度为O(n^2)
//属于稳定算法
3,1,8,2,5,7,9,4,6
132578469
123574689
123546789
123456789
123456789
123456789
123456789
123456789
123456789
void bubbleSort(int* arr, int length)
{
int i, j;
for(int i=0; i<length; i++)
for(int j=1; j<length-i;j++)
{
if(arr[j]<arr[j-1])
swap(&arr[j],&arr[j-1]);
}
}
//改进的冒泡排序:设置一个标志,如果这一趟发生了交换,则为true,否则为false。
//明显如果有一趟没有发生交换,说明排序已经完成。
void bubbleSort(int* arr, int length)
{
int i;
bool flag = true;
while(flag)
{
flag = false;
for(int i=1; i<length; i++)
{
if(arr[i]<arr[i-1])
swap(&arr[i],&arr[i-1]);
flag=true;
}
length--;
}
}
*/
/*
//直接插入排序:选取第一个数字作为初始有序数列,
//将后面的无序数列依次插入有序数列的合适位置
//最坏时间复杂度为O(n^2)
//属于稳定算法
3,1,8,2,5,7,9,4,6
138257946
138257946
123857946
123587946
123578946
123457896
123456789
123456789
void insertSort(int* arr, int length)
{
int i,j;
for(i=1; i<length;i++)
{
if(arr[i]<arr[i-1])
{
int temp = arr[i]; //在序列中找到第一个比前一个数字大的数字的索引
for(j = i-1;j>=0 && arr[j]>temp;j--) //找到放temp的正确位置,且不越界
{
arr[j+1] = arr[j];//将前面比temp大的数字后移
}
arr[j+1] = temp; //在正确位置放置temp
}
}
}
*/
/*
//希尔排序:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。
//所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;
//然后,取第二个增量d2<d1重复上述的分组和排序,
//直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
//希尔排序的时间复杂度与增量序列的选取有关,采用希尔增量时间复杂度为O(n^2)
//采用Hibbard增量时间复杂度为O(n^3/2);希尔排序相对于前面两种有较大改进
//属于不稳定算法
void shellSort(int* arr, int length)
{
int i,j,d,temp;
for(d = length/2; d>0; d=d/2) //采用希尔增量
{
for(i=d;i<length;++i) //分组插入排序
{
if(arr[i]<arr[i-d])
{
temp = arr[i];
for(j=i-d;j>=0&&arr[j]>temp;j=j-d)
{
arr[j+d] = arr[j];
}
arr[j+d] = temp;
}
}
}
}
*/
/*
//直接选择排序:直接选择排序和直接插入排序类似,都将数列分为
//有序区和无序区,所不同的是直接选择排序是将无序区中最小的数
//直接放在有序区的末尾。
//它的时间复杂度是O(n^2)
//不稳定算法
3,1,8,2,5,7,4,6
13825746
12835746
12385746
12348756
12345876
12345687
12345678
void selectSort(int* arr, int length)
{
int i,j;
for(i = 0;i<length-1;i++)
{
for(j=i+1;j<length;j++)
{
if(arr[j]<arr[i])
swap(&arr[i],&arr[j]);
}
}
}
*/
/*
//归并排序:将数列分成两组,如果两组子数列有序,就可以方便地将它们进行排序。
//如果它们无序,则再将它们各自拆分成两组子数列,依次类推。
//它的最好,最坏和平均时间复杂度都为O(n*logn),空间复杂度为O(n)
//属于稳定排序算法
3,1,8,2,5,7,9,4,6
138257946
138257946
123584679
123456789
void merge(int* arr,int* temp_arr,int first,int last,int mid)
{
int arrIndex1 = first;
int arrIndex2 = mid+1;
int index = first;
while(arrIndex1<=mid && arrIndex2<=last)
{
if(arr[arrIndex1]<=arr[arrIndex2])
temp_arr[index++] = arr[arrIndex1++];
else
temp_arr[index++] = arr[arrIndex2++];
}
while(arrIndex1<=mid)
temp_arr[index++] = arr[arrIndex1++];
while(arrIndex2<=last)
temp_arr[index++] = arr[arrIndex2++];
for(int i=0;i<index;i++) //必须将数组赋值放在这里,否则会导致排好的数列又复原
arr[i] = temp_arr[i];
}
void merge_sort(int* arr,int* temp_arr,int first,int last)
{
if(first<last)
{
int mid = (first+last)/2; //递归的拆分
merge_sort(arr,temp_arr,first,mid);
merge_sort(arr,temp_arr,mid+1,last);
merge(arr,temp_arr,first,last,mid); //合并子数列
}
}
void mergeSort(int* arr, int length)
{
if(arr == NULL || length <=0)
return;
int* temp_arr=new int[length]; //辅助数列
merge_sort(arr,temp_arr,0,length-1);
delete[] temp_arr;
}
*/
/*
//快速排序:通过一趟排序将要排序的数据分割成独立的两部分,
//其中一部分的所有数据都比另外一部分的所有数据都要小,
//然后再按此方法对这两部分数据分别进行快速排序,
//整个排序过程可以递归进行,以此达到整个数据变成有序序列。
//最坏情况O(n*n),平均为O(nlogn);在同为O(nlogn)中,效率最高
//不稳定算法
3,1,8,2,5,7,9,4,6(基准选最后一个)
312546879
312456879
123456789
int partition(int* arr, int start,int end)
{
int standard = arr[end];
int small = start-1;
for(int i=start; i<end; ++i)
{
if(arr[i]<standard)
{
++small;
if(i!=small)
{
swap(&arr[i],&arr[small]);
}
}
}
++small;
swap(&arr[small],&arr[end]);
return small;
}
void quickSort(int* arr, int start,int end)
{
if(arr == NULL)
return;
if(start<end)
{
int index = partition(arr,start,end);
quickSort(arr,start,index-1);
quickSort(arr,index+1,end);
}
}
*/
/*
//堆排序:堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,
//使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
//时间复杂度:O(N*logN)
//属于不稳定算法
void heapAdjust(int* arr,int length,int i)
{
int nChild;
int parent;
for(parent=arr[i]; 2*i+1<length; i=nChild)
{
nChild = 2*i+1;
//找出子节点中较大值,并确保不越界
if(nChild<length-1 && arr[nChild]<arr[nChild+1])
++nChild;
//如果找到的子节点大于父节点,将子节点往上移动
if(arr[nChild]>parent)
{
arr[i] = arr[nChild];
arr[nChild] = parent;
}
else
break;
}
}
void heapSort(int* arr, int length)
{
// 调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
//length/2-1是第一个非叶节点
for(int i=(length-1)/2; i>=0; --i)
heapAdjust(arr,length,i);
// 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
for(int i=length-1; i>0; --i)
{
swap(&arr[0],&arr[i]); //确保最后的元素最大
heapAdjust(arr,i,0); //保证整棵树符合二叉堆性质
}
}
*/
void test1()
{
const int length = 9;
int arr[] = {3,1,8,2,5,7,9,4,6};
//bubbleSort(arr,length);
//insertSort(arr,length);
//shellSort(arr,length);
//selectSort(arr,length);
//mergeSort(arr,length);
//quickSort(arr,0,length-1);
//heapSort(arr,length);
for(int i =0;i<length;i++)
printf("%d\t",arr[i]);
}
int main()
{
test1();
return 0;
}
== 参考 http://my.csdn.net/mmc_maodun