算法基础——1.排序
Posted sylvan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法基础——1.排序相关的知识,希望对你有一定的参考价值。
排序算法
交换排序类:冒泡排序、快速排序
选择排序类:简单选择排序、堆排序
插入排序类:直接插入排序、希尔排序
冒泡排序
冒泡排序(Bubble Sort),排序的基本思想为两两比较小相邻数据的关键字,如果顺序为反则进行交换,直到没有反序的记录为止。
冒泡排序有多种变化,其三种不同实现的代码如下:
//OS:Win | Terminal:Cmder | Editor:Atom | Language:c
void Swap(int *a , int *b){
int temp = *a;
*a = *b;
*b = temp;
}
//最容易的排序,从第一个元素开始向后与每一个元素进行比较,交换得到最小的元素,放在第i个位置
//这样排序进行较多次无用的比较,当然,这并不是所谓的冒泡排序
void SimpleBubble(int array[] , int length){
for(int i = 0 ; i < length ; i++){
for(int j = i+1 ; j < length ; j++){
if(array[i] > array[j]){
Swap(&array[i],&array[j]);
}
}
}
}
//从第一个位置开始,由下往上两两元素进行比较,判断并交换得到最小值
//这样排序依次循环确定第i个位置的元素
void LittleBubble(int array[] ,int length){
for(int i =0 ; i < length ; i++){
for(int j = length -1 ; j > i ;j --){
if(array[j] < array[j-1]){
Swap(&array[j],&array[j-1]);
}
}
}
}
//增加标志位isSwap来表示是否存在反序或者是否进行过交换操作
//直到序列没有反序记录为止
void BubbleSort(int array[] , int length){
int isSwap = 1;
for(int i = 0 ; i < length ; i ++){
if(isSwap){
isSwap = 0;
for(int j = length -1 ; j > i ; j --){
if(array[j] < array[j-1]){
Swap(&array[j],&array[j-1]);
isSwap = 1;
}
}
}
}
}
void Print(int array[] , int length){
for (int i = 0 ; i < length ;i++){
printf(" %d",array[i]);
}
}
int main(){
int array[] = {6,5,3,1,0,2,9,8,4,7};
BubbleSort(array,10);
Print(array,10);
return 0;
}
简单选择排序
简单选择排序(Simple Selection Sort),基本思想是:标记第i个元素为最小值下标min开始向后进行遍历比较,不断更新最小值下标min,结束该次循环后判断min是否改变,若改变即交换i位置元素及min位置的最小元素。
void SelectSort(int array[] , int length){
int min;
for(int i = 0 ; i <length ; i++){
min = i ; //Notice1:以第一个元素为最小开始向后遍历比较
for(int j = i+1 ; j < length ; j++){ //Notice2:j从i+1开始向后遍历
if(array[j] < array[min]){ //Notice3:每次都是array[j]与array[min]进行比较,来确定和更新最小值所在下标
min = j;
}
}
if(min != i){
Swap(&array[i] ,&array[min]);
}
}
}
直接插入排序
直接插入排序(Straight Insertion Sort)是最简单的排序算法之一,主要思想是保证位置0到第i-1位置上的元素为已排序状态,即插入排序利用这样的事实,从i位置循环进行排序。
void InsertionSort(int array[] , int length ){
int i,j,temp;
//Notice1:开始以第一个数据为有序序列,从第二个数据开始排序
for(i = 1 ; i <length ; i++){
if(array[i] < array[i-1]){ //Notice2:当当前数据大于前一个时,开始向前插入
temp = array[i]; //保存此时的值,为前方较大元素空出位置
for(j = i -1 ; j>=0 && array[j] > temp ; j--){ //向前循环直至下标小于0,或者值比当前值更小
array[j+1] = array[j]; //依次后移
}
array[j+1] = temp; //此时j位置的元素小于当前值,所以插入其后一位j+1即可
}
}
}
希尔排序
希尔排序(Shell Sort)是冲破二次时间屏障的第一批算法之一。主要思想是:通过比较一定间隔的元素来工作;各趟比较所用的距离(希尔增量)随着算法的进行而逐渐减小,直到比较相元素的最后一趟排序为止。因此,希尔排序也称为缩小增量排序。
void ShellSort(int array[] , int length){
int i,j,temp,gap;
int judgeCount = 0, changeCount = 0;
//Notice1:设置希尔增量序列初始值 gap = length/2 ,一直循环值gap=1进行最后一次插入排序
for(gap = length/2 ; gap >0 ; gap /=2){
//Notice2:内层嵌套一个直接插入循环
for(i = gap ; i < length ; i++ ){
judgeCount++;
if(array[i] < array[i - gap]){
temp = array[i];
for(j = i - gap ; j >= 0 && array[j] > temp ; j -=gap){
array[j+gap] = array[j];
changeCount++;
}
array[j+gap] = temp;
}
}
}
printf("Judge Count : %d ,Change Count : %d .
", judgeCount,changeCount);
}
堆排序
堆排序(Heap Sort)是一个非常稳定的算法,排序平均使用的比较只比最坏情况界指出的略少。
void AdjustHeap(int array[] , int i , int length){
//Notice2:保存开始节点的值为temp,减少直接交换的次数
int temp = array[i];
for(int j = i*2 +1 ; j <length ; j = j*2+1){
if(j+1 < length && array[j] < array[j+1])
j++;
if(array[j] < temp ) //Notice3:循环对temp中保存的值进行比较
break;
array[i] = array[j];
i = j;
}
array[i] = temp; //Notice4:最后在temp合适的位置上进行赋值放置
}
void HeapSort(int array[] ,int length){
//Notice1:首先从最后一个非页子节点开始,由右向左、由下至上开始进行最大堆的构造
for(int i = length/2 ; i >= 0 ; i --){
AdjustHeap(array , i ,length);
}
for(int i = length -1 ; i > 0 ; i --){
Swap(&array[0],&array[i]);
AdjustHeap(array, 0, i );
}
}
快速排序
快速排序(Quick Sort)是在实践中最快的已知排序算法,平均运行时间是O(N log N)。快速排序之所以快是因为其精炼的、高度优化的内部循环。最坏情况的性能为O(N2),如今高度优化后的快速排序简单易懂并且不难证明。
和归并排序一样,快速排序也是一种分治的递归算法。
将数组array进行快速排序QuickSort的基本算法由以下简单的四步组成:
- 1.如果数组长度为0或者1,则直接返回;
- 2.使用Median3或其他方法获取枢纽元素pivot;
- 3.划分子集;
- 4.递归调用QuickSort
REF
书籍:
数据结构与算法分析、大话数据结构
以上是关于算法基础——1.排序的主要内容,如果未能解决你的问题,请参考以下文章