排序

(未完待续)

一 插入排序

1.方法概述:定义两个“数组”A,B。A存放未排序元素,B存放已排序元素(初始时,所有元素存放在A中,B为空),从A中取出一个元素a,

(1)第一个取出的元素a直接放入已排序数组中

(2)其他的a与B的最后一个元素bm相比较,若a>= bm, 则a放于bm后;

若a<bm,则将a与bm-1比较,重复a和bm相同的操作,直到找到一个bn <= a,将a放于bn后。

(3)再次取出a,重复操作(2),直到A为空。

实现时,为节省空间,A和B实际上是同一数组的的两个部分,低序部分(即数组索引值较小的部分)为B,高序部分A。操作(1)可省略;并且数组多了一个空余的元素,即数组下标为0的元素,用于作为排序算法的temp,实际存储的元素索引从1到n.

2.实现(c语言)

//const int MAX = 255;  //数组最大长度,这里不需要该值
typedef  int Item;  //数组类型,这里取int
void InsertSort(int n, Item A[])  // n为数组待排序的元素数目,即数组的最大索引,注意不为n-1!
{
    int i, j;
    for (i = 2; i <= n; i++)
        if (A[i-1] > A[i])
        {
            A[0] = A[i];
             j = i - 1;
            do
            {
                A[j + 1] = A[j];
                j--;
            }while(A[j] > A[0]);
        }
     A[j + 1] = A[0];
}


二 冒泡排序

1.方法概述:依次将最小,次小,和倒数第三小……的元素依次排到数组的第一位,第二位,第三位……的排序方法。每次排序中最小的元素是在比较的过程中确定的。虽然一次排序过程中最小的元素不固定,但是一次排序完毕,总能保证本次排序最小的元素在最前面(即已排序数组部分的最后一位,未排序数组部分的前一位)。

  实现时,若某一次排序过程未发生元素交换,则表明数组已排好,退出过程。

2.实现(c)

void BubbleSort(int n, const Item A[])
{
    int i, j;
    for (i = 1; i <= n; i ++)
    {
        exchange = 0;//交换标志,若未发生交换,退出过程
        for (j = n - 1; j >= i; j--)
            if (A[j+1] < A[j])
            {
                A[0] = A[j + 1];
                A[j + 1] = A[j];
                A[j] = A[j + 1];
            }
        if (!exchange)
            return;
    }
}

三 快速排序

1.方法概述:取未排序数组中的某个元素,将剩余数组中比其小的元素放在左边,比起大的元素放在右边的排序方法。实际上,左边部分和右边部分内部未实现排序,因此还需要对两边的序列重复相同的操作;已排好序的选取的元素(基准元素)。

实现时,采用递归操作;定义两个函数,主函数根据基准位置对两边实现排序,子函数用于划分两边的元素,返回基准位置。

2.实现(c语言)

int Partition(Item * A, int i,  int j) 
{
    int pivot = A[i];   //基准元素值
    while(i < j) 
    {
        while (i < j &&pivot <= A[j])  j--;
        if(i < j) A[i++] = A[j];
        while (i < j && pivot >= A[i])i++;
        if (i < j)  A[j--] = A[i];
    }
    A[i] = pivot;
    return i;
}

void QuickSort(Item *A, int low, int high)
{
    int pivotpos;//基准位置
    if (low < high)
    {
        pivotpos = Partition(low, high);
        QuickSort(low, pivotpos - 1);
        QuickSort(pivotpos + 1, high);
    }
}


四 希尔排序(插入排序改进算法)

1.方法概述:相比插入排序,希尔排序引进了“增量”的概念,即相邻排序元素之间的间隔。插入排序的增量为1,换言之,待插入元素与前一个元素进行比较,两者下标相差为1;而希尔排序的增量每次排序均发生变化,不断减小,每次排序的子序列的下标之差不为1,即为增量值, 而排序算法的本质依然是插入排序。算法如下:

  (1)计算本次排序增量。本次增量值与上次增量值计算而来。

  (2)使用增量对数组进行排序。

  (3)重复(1)(2),直到增量为1,结束。

2.实现(C语言)

void ShellPass(Item A[ ], int d, int n)
{
    int i, j;
    for (int i = d + 1; i <= n; i++)
        if (A[i] < A[i - d])
        {
            A[0] = A[i];
            j = i - d;
            do
            {
                A[j + d] = A[j];
                j = j - d; 
            }while (j > 0 && A[j]  > A[0]);
            A[j + d ] = A[0];
       }
}

void ShellSort(Item A[ ], int n)
{
    int increment = n;
    do
    {
        increment = increment/3 + 1;
        ShellPass(A, increment, n);
    }while (increment > 1);
}


五 选择排序

1.算法概述:选出最小的元素,放入数组的相应位置。选择排序与插入排序的不同之处:

选择排序:从未排序序列部分选出最小的元素,放入已排序序列尾部;

插入排序:从未排序序列的头部取出一个元素,在已排序数组依次由尾部到头部逐个元素进行比较,找到插入位置

2.实现(C语言)

void SelectSort(int n)
{
    int i, j, k;
    for (i = 1; i < n; i++)
    {
        k = i;
        for (j = i + 1; j <= n; j++)
            if (R[j] < R[k])
                k = j;
        if (k != i)
        {
            R[0] = R[i];
            R[i] = R[k];
            R[k] = R[0];
        }    
    }
}


六 堆排序

1.方法概述:

(1)堆:一种数据结构,基于完全二叉树,并满足:T[i] 大于T[2i]和T[2i+1] 或者 T[i] 小于 T[2i]和T[2i+1],即对于一个非叶子节点,要么比两个子节点都大,要么比它们小, 前者称为大堆根,后者称为小根堆。对于小根堆,根节点一定为最小值,对于大堆根,根节点一定为最大值。

(2)堆排序通过”建立堆-取出堆顶元素“的循环得到已排序的序列。算法为:

(1)建立堆。方向为自底向顶。初始时堆的边界与序列的边界相同

(2)交换堆顶元素和堆尾元素,修改堆边界的上限(减1),

(3)若堆中不止一个元素,重复操作(1)(2)。

2.实现

void Heapify(Item A[ ], int s, int n)
{
    int j, temp = A[s];
    j = 2* s;
    while (j <= m)
    {
        if (A[j] > A[j+1] && j < m) j++;
        if (temp < A[j]) break;
        A[s] = A[j];
        s = j;
        j = 2 * j;
    }
    A[s] = temp;
}

void BuildHeap(Item A[ ], int n)
{
    int i;
    for (i = n / 2; i > 0; i--)
        Heapify(A, i, n);
}

void HeapSort(Item A[ ], int n)
{
    int i;
    BuildHeap(A, n);
    for (i = n; i > 1; i--)
    {
        A[0] = A[1];
        A[1] = A[i];
        A[i] = A[0];    
        Heapify(A, 1, i - 1);
    }
}


七 归并排序

1.方法概述:将未排序数组分成两部分,先分别进行排序,然后进行归并。对于部分序列,采取相同的操作。归并排序是一个递归的过程。

2.实现(C语言)

void Merge(Item A[ ], int low, int m, int high)
{
    int i = low, j = m + 1, p = 0;
    Item *At = (int *)malloc((high - low + 1) * sizeof*(Item));
    if (At == NULL)
    {
        puts("malloc failed!");
        return;
    }
    while (i <= m && j <= high)
        At[p++] = (A[i] < A[j]) ? A[i++] : A[j++];
    while (i <= m) At[p++] = A[i++];
    while (j <= high) At[p++] = A[j++];
    for (i = low, p = 0; i <= high; i++, p++)
        A[i] = At[p];
    free(At);
}

void MergeSort(Item A[ ], int low, int high)
{
    int mid;
    if (low < high)
    {
        mid = (low + high) / 2;
        MergeSort(A, low, mid);
        MergeSort(A, mid + 1,  high);
        Merge(A, low, mid, high);
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值