常见排序算法(描述与实现)

效率比较

排序算法效率比较

算法实现

◎冒泡排序

冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

冒泡排序算法流程如下:

  • 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  • 针对所有的元素重复以上的步骤,除了最后一个。
  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

代码实现

 void bubbleSort(int a[],int len)
 {
 	int i, j, temp;
	for (j=0; j<len; j++)
	{
		for (i=0; i<len-j; i++)
		{
			if (a[i] > a[i+1])
			{
				temp = a[i];
				a[i] = a[i+1];
				a[i+1] = temp;
			}
		}
	}
}

◎快速排序

快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),快速排序是对冒泡排序的一种改进,由C. A. R. Hoare在1962年提出。

快速排序算法流程如下:

  • 从数列中挑出一个元素,称为"基准"(pivot)。
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

代码实现

/*
* 函数参数:
* a[]: 待排序数组
* start:数组起始下标
* end:数组末位下标
*/

void quickSort(int a[], int start, int end)
{
    if(start >= end)
    {
        return ;
    }
    int low = start;
    int high = end;
    int key = a[start];		// 基准

    while(low < high)
    {
        while(low < high && key <= a[high])
        {
            high--;
        }
        a[low] = a[high];

        while(low < high && key >= a[low])
        {
            low++;
        }
        a[high] = a[low];
    }

    a[low] = key;
    quickSort(a, start, low-1);
    quickSort(a, low+1, end);
}

◎插入排序

插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

代码实现

void InsertSort(int a[],int len)
{
    int i, j, temp;
    for (i=0; i<len; i++)
    {
        j = i-1;
        temp = a[i];
        while (j>=0 && temp<a[j])
        {
            a[j+1] = a[j];
            j--;
        }
        a[j+1] = temp;
    }
}

◎希尔排序

希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。

希尔排序算法流程如下:

  • 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序。
  • 随着增量逐渐减小,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

代码实现

void shellSort(int a[], int len)
{
	int i, j, temp;
	int gap=0;
	
    while (gap <= len)		// 生成初始增量
    {
        gap = 3*gap + 1;
    }
    while (gap >= 1)
    {
        for (i=gap; i<len; i++)
        {
            j = i-gap;
            temp = a[i];
            while (j>=0 && a[j]>temp)
            {
                a[j+gap] = a[j];
                j = j-gap;
            }
            a[j+gap] = temp;
        }
        gap = (gap-1) / 3;	// 递减增量
    }
}

◎选择排序

选择排序(Selection sort)是一种简单直观的排序算法。

选择排序算法流程如下:

  • 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  • 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
  • 以此类推,直到所有元素均排序完毕。

代码实现

void selectSort(int a[], int len)
{
    int i;         // 有序区的末尾位置
    int j;         // 无序区的起始位置
    int min;       // 无序区中最小元素位置
    int temp;

    for (i=0; i<len; i++)
    {
        min=i;

        for (j=i+1; j<len; j++)
        {
            if(a[j] < a[min])
                min=j;
        }

        if (min != i)
        {
        	temp = a[i];
        	a[i] = a[min];
        	a[min] = temp;
		}
    }
}

◎堆排序

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。

堆排序算法流程如下:

  • 将待排序的序列构造成一个大顶堆(或小顶堆)。
  • 此时,整个序列的最大值就是堆顶的根结点。将它移走(就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值)。
  • 然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值。
  • 如此反复执行,便能得到一个有序序列了。

代码实现

/*
* parentIndex:父结点下标
* leftIndex: 左孩子结点下标
*/

// 调整大根堆
void adjustHeap(int a[], int parentIndex, int len)
{
	int leftIndex, temp;
	temp = a[parentIndex];

	for (leftIndex=2*parentIndex; leftIndex<=len; leftIndex*=2)
	{
		if (leftIndex<len && a[leftIndex] < a[leftIndex+1])
		{
			leftIndex++;
		}
		if (temp > a[leftIndex])
		{
			break;
		}
		a[parentIndex] = a[leftIndex];
		parentIndex = leftIndex;
	}
	a[parentIndex] = temp;
}

// 交换元素
void swap(int arr[], int i, int j)
{
	int temp;
	temp = arr[i];
	arr[i] = arr[j];
	arr[j] = temp;
}

// 堆排序
void heapSort(int arr[],int len)
{
	int index;
	for (index=len/2 ; index>0; index--)
	{
		adjustHeap(arr, index, len);
	}
	for (index=len; index>1; index--)
	{
		// 交换堆顶元素与末尾元素
		swap(arr, 1, index);
		
		adjustHeap(arr, 1, index-1);
	}
}

◎归并排序

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

归并排序算法流程如下:

  • 将待排序数组递归的分解至最小,分成许多个左右子序列。
  • 对每个子序列分别进行排序。
  • 将已有序的子序列合并排序,使子序列段间有序,得到完全有序的序列。

代码实现

#include <stdio.h>

// 合并数组
void Merge(int sourceArr[],int tempArr[], int start, int mid, int end)
{
    int i = start, j=mid+1, k = start;
    while (i!=mid+1 && j!=end+1)
    {
        if (sourceArr[i] > sourceArr[j])
            tempArr[k++] = sourceArr[j++];
        else
            tempArr[k++] = sourceArr[i++];
    }

	// 追加剩余元素
    while (i != mid+1)
        tempArr[k++] = sourceArr[i++];
    while (j != end+1)
        tempArr[k++] = sourceArr[j++];

    for (i=start; i<=end; i++)
        sourceArr[i] = tempArr[i];
}

// 归并排序
void MergeSort(int sourceArr[], int tempArr[], int start, int end)
{
    int mid;
    if(start < end)
    {
        mid = start + (end-start) / 2;
        MergeSort(sourceArr, tempArr, start, mid);
        MergeSort(sourceArr, tempArr, mid+1, end);
        Merge(sourceArr, tempArr, start, mid, end);
    }
}

// 打印数组
void printArray(int a[], int n)
{
	int i;
	for (i=0; i<n; i++)
	{
		printf("%3d", a[i]);
	}
	printf("\n");
}

void main()
{
	int sourceArr[9] = {44,33,11,22,66,88,77,55,99};
	int n = sizeof(sourceArr) / sizeof(int);
	int tempArr[9];

	printArray(sourceArr, n);
	MergeSort(sourceArr, tempArr, 0, n-1);
	printArray(tempArr, n);
}
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值