风言枫语  

插入排序:简单地说,就是就将无序序列依次插入到有序序列中。
算法描述:
1. 从第一个元素开始,该元素可以认为已经被排序
2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5. 将新元素插入到该位置后
6. 重复步骤2~5
时间复杂度:
最坏情况;O(n^2);
平    均:O(n^2);

/*********** 插入排序 ************/
void InsertSort(int *p, const int len)
{
    assert(p != NULL);

    int i;
    int j;
    int temp;

    for (i = 1; i < len; i++)
    {
        temp = p[i];
        for (j = i-1; j >= 0; j--)
        {
            if (p[i] > temp)
            {
                p[j+1] = p[j];
            }
            else
            {
                break;
            }
        }
        p[j+1] = temp;
    }
}


冒泡排序: 一种简单地排序算法。
算法描述:
1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这样会使得最后的元素为最大值;
3. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
时间复杂度:
最坏情况;O(n^2);
平    均:O(n^2);

/*********** 冒泡排序 ************/
void BubbleSort(int *p, const int len)
{
    assert(p != NULL);

    int i;
    int j;
    int temp;

    for (i = 0; i < len; i++)
    {
        for (j = 0; j < len-i-1; j++)
        {
            if (p[j] > p[j+1])
            {
                temp = p[j];
                p[j] = p[j+1];
                p[j+1] = temp;
            }
        }
    }
}

/*********** 冒泡排序 ************/
void BubbleSort(int *p, const int len)
{
    assert(p != NULL);

    int i;
    int j;
    int temp;

    for (i = 0; i < len; i++)
    {
        for (j = i+1; j < len; j++)
        {
            if (p[i] > p[j])
            {
                temp = p[i];
                p[i] = p[j];
                p[j] = temp;
            }
        }
    }
}


选择排序:从未排序列中找到最大(小)元素将其置于合适的位置。
算法描述:
1. 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
2. 从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。
3. 重复步骤2,直到所有元素均排序完毕。
时间复杂度:
最坏情况;O(n^2);
平    均:O(n^2);

/*********** 选择排序 ************/
void SelectSort(int *p, const int len)
{
    assert(p != NULL);

    int i;
    int j;
    int k;
    int temp;

    for (i = 0; i < len-1; i++)
    {
        k = i;
        for (j = i+1; j < len; j++)
        {
            if (p[k] > p[j])
            {
                k = j;
            }
        }

        if (k != i)
        {
            temp = p[i];
            p[i] = p[k];
            p[k] = temp;
        }
    }
}


快速排序:通过一趟排序将待排记录分隔成独立的两部分,其中以部分记录的关键字比另一部分记录的关键字小,
则可分别对这两部分记录继续进行排序,以达到整个序列有序。
算法描述:
1. 设置两个变量low、high,排序开始的时候:low=0,high=N-1;
2. 以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3. 从high开始向前搜索,即由后开始向前搜索(high--),找到第一个小于key的值p[high],将值为key的项与p[high]交换;
4. 从low开始向后搜索,即由前开始向后搜索(low++),找到第一个大于key的p[low],将值为key的项与p[low]交换;
5. 重复第3、4、5步,直到low=high; (3,4步中,没找到符合条件的值,即3中p[high]不小于key,4中p[low]不大于key的时候改变low、high的值,使得high=high-1,low=low+1,直至找到为止。找到符合条件的值,进行交换的时候low,high指针位置不变。另外,low==high时令循环结束)。
时间复杂度:
最坏情况:O(n^2);
平    均:O(nlogn);

/*********** 调整分区 ************/
int Partition(int *p, const int low, const int high)
{
    assert(p != NULL);

    int i = low;
    int j = high;
    int key = p[low];

    while (i < j)
    {
        while (i < j && key <= p[j])
        {
            j--;
        }
        if (i < j)
        {
            p[i++] = p[j];
        }

        while (i < j && key > p[i])
        {
            i++;
        }
        if (i < j)
        {
            p[j--] = p[i];
        }
    }
    p[i] = key;

    return i;
}


/*********** 快速排序 ************/
void QuickSort(int *p, const int low, const int high)
{
    assert(p != NULL);

    int pos = Partition(p, low, high);
    if (low < high)
    {
        QuickSort(p, low, pos-1);	// 递归地对关键字前面的序列进行排序
        QuickSort(p, pos+1, high);  // 递归地对关键字后面的序列进行排序
    }
}


堆排序:是指利用堆这种数据结构所设计的一种排序算法。
算法思想:
1. 初始化操作:将R[1..n]构造为“大顶堆”;
2. 将当前无序区的堆顶记录R[0]和该序列的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆);
3. 直到所有元素有序;
时间复杂度:
最坏情况;O(nlogn);
平    均:O(nlogn);

/*********** 构建大顶堆 ************/
void AdjustTop(int *p, const int len)
{
    assert(p != NULL);

    int pos = len / 2 - 1;
    int t;
    int temp;

    while (pos >= 0)
    {
        if (pos*2+2 == len)	   // 只有自由左子树的情况
        {
            t = p[pos*2+1] > p[pos] ? pos*2+1 : pos;
        }
        else	// 左右子树都存在
        {
            t = p[pos*2+1] > p[pos*2+2] ? pos*2+1 : pos*2+2;
            t = p[t] > p[pos] ? t : pos;
        }

        if (t != pos)	// 加此条件判断以减少交换次数
        {
            temp = p[pos];
            p[pos] = p[t];
            p[t] = temp;
        }

        pos--;
    }
}


/*********** 堆排序 ************/
void HeapSort(int *p, const int len)
{
    assert(p != NULL);

    int i;
    int temp;
	
    for (i = 0; i < len; i++)
    {	
        AdjustTop(p, len-i);	//对剩余元素重新构建“大顶堆”
        temp = p[0];
        p[0] = p[len-i-1];
        p[len-i-1] = temp;
    }
}


各种内部排序方法的比较:
1. 就平均时间性能而言,快速排序最佳,其所需时间最少,但快速排序在最坏情况下的性能不如堆排序;
2. 由于堆排序在最坏情况下的时间复杂度和平均时间复杂度差不多,所以待排序列中元素初始时的顺序对该排序算法没有太大影响。
2. 从方法的稳定性来看,所有时间复杂度为O(n^2)的简单排序法都是稳定的(包括插入排序、冒泡排序、选择排序)。一般来说,排序过程中的“比较”是在“相邻的两个记录关键字”间进行的排序方法都是稳定的。

posted on 2013-08-31 22:58  风言枫语  阅读(195)  评论(0编辑  收藏  举报