常用排序算法

//常用的排序算法

include <iostream>

using namespace std;

typedef int ElemType;

/*
1、插入排序
(1)直接插入排序算法
算法思想:将等排序列划分为有序与无序两部分,然后再依次将无序部分插入到已经有序的部分,最后

就可以形成有序序列。
操作步骤如下:
1)查找出元素L(i)在表中的插入位置K;
2)将表中的第K个元素之前的元素依次后移一个位置;
3)将L(i)复制到L(K)。

时间复杂度为:O(n^2)
*/
void InsertSort(ElemType arr[], int length)
{
int i, j;
ElemType guard; // 哨兵

for (i = 1; i < length; ++i)  
{  
    if (arr[i] < arr[i-1]) // 在无序部分寻找一个元素,使之插入到有序部分后仍然有序  
    {  
        guard = arr[i];// 复制到“哨兵”  
      
        // 将第i个元素之前的元素依次后移一个位置  
        for (j = i - 1; arr[j] > guard; j--)  
        {  
            arr[j + 1] = arr[j];  
        }  

        arr[j + 1] = guard; // 复制到插入位置  
    }  
}  

}

/*
2、折半插入排序
使用于排序表为顺序存储的线性表
在查找插入位置时,采用折半查找
算法思想是:
1)设置折半查找范围;
2)折半查找
3)移动元素
4)插入元素
5)继续操作1)、2)、3)、4)步,直到表成有序。
*/
void BinaryInsertSort(ElemType arr[], int length)
{
int i, j, low, high, mid;
ElemType tmp;

for ( i = 1; i < length; ++i )  
{  
    tmp = arr[i]; // 复制到哨兵  
      
    // 设置折半查找范围  
    low = 0;        
    high = i;  

    while (low <= high) // 折半查找  
    {  
        mid = (low + high) / 2;  

        if (arr[mid] > tmp) // 在左半部分查找  
        {  
            high = mid - 1;  
        }  
        else  
        {  
            low = mid + 1; // 在右半部分查找  
        }  
    }  

    // 移动元素  
    for ( j = i - 1; j >= high + 1; --j )  
    {  
        arr[j + 1] = arr[j];  
    }  

    arr[j + 1] = tmp;  
}  

}

/*
3、希尔(Shell)排序
基本思想:
先将待排序的表分割成若干个形若L[i, i+d, i+2d, ..., i+kd]的“特殊”子表,分别进行直接插入排序,
当整个表已呈“基本有序”时,再对全体记录进行一次直接插入排序。
算法过程:
1)先取一个小于n的步长d1,把表中全部记录分成d1个组,所有距离为d1的倍数的记录放在同一组中,在各
组中进行直接插入排序;
2)然后取第二个步长d2 < d1, 重复步骤1
3)直到dk = 1,再进行最后一次直接插入排序
*/

void ShellSort(ElemType arr[], int length)
{
int i, j, dk = length / 2;
ElemType tmp;

while (dk >= 1)// 控制步长  
{  
    for (i = dk; i < length; ++i)  
    {  
        if (arr[i] < arr[i - dk])  
        {  
            tmp = arr[i]; // 暂存  

            // 后移  
            for (j = i - dk; j >= 0 && tmp < arr[j]; j -= dk)  
            {  
                arr[j + dk] = arr[j];  
            }  

            arr[j + dk] = tmp;  
        }  
    }  

    dk /= 2;  
}  

}

/*
4、冒泡排序算法
基本思想:
假设待排序的表长为n, 从后向前或从前向后两两比较相邻元素的值,若为逆序,则交换之,直到序列比较完。
这样一回就称为一趟冒泡。这样值较大的元素往下“沉”,而值较小的元素入上“浮”。
时间复杂度为O(n^2)
*/
void BubbleSort(ElemType arr[], int length)
{
int i, j;
ElemType tmp;

for (i = 0; i < length - 1; ++i)// 趟次  
{  
    for (j = i + 1; j < length; ++j)  
    {  
        if (arr[i] > arr[j])  
        {  
            tmp = arr[i];  
            arr[i] = arr[j];  
            arr[j] = tmp;  
        }  
    }  
}  

}

/*
5、快速排序算法
基本思想:基于分治法,在待排序的n个元素中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的
两部分L[1..k-1]和L[k+1 .. n],使得第一部分中的所有元素值都小于pivot,而第二部分中的所有元素值都大于pivot,
则基准元素放在了其最终位置L(K)上,这个过程为一趟快速排序。而后分别递归地对两个子表重复上述过程,直到每
部分内只有一个元素或为空为止,即所有元素都放在了其最终位置上。
*/

int Partition(ElemType arr[], int left, int right)
{
ElemType pivot = arr[left]; // 以当前表中第一个元素为枢轴值

while (left < right)  
{  
    // 从右向左找一个比枢轴值小的元素的位置  
    while (left < right && arr[right] >= pivot)   
    {  
        --right;  
    }  

    arr[left] = arr[right]; // 将比枢轴值小的元素移动到左端  

    // 从左向右查找比枢轴值大的元素的位置  
    while (left < right && arr[left] <= pivot)  
    {  
        ++left;   
    }  

    arr[right] = arr[left];// 将比枢轴值大的元素移动到右端  
}  

arr[left] = pivot; // 将枢轴元素放在最终位置  

return left;  

}

void QuickSort(ElemType arr[], int left, int right)
{
if (left < right)
{
int pivotPos = Partition(arr, left, right); // 划分
QuickSort(arr, left, pivotPos - 1); // 快速排序左半部分
QuickSort(arr, pivotPos + 1, right); // 快速排序右半部分
}
}

/*
6、简单选择排序算法
基本思想:
假设排序表为L[1...n],第i趟排序从表中选择关键字最小的元素与Li交换,第一趟排序可以确定一个元素的
最终位置,这样经过n-1趟排序就可以使得整个排序表有序。
*/

void SelectSort(ElemType arr[], int length)
{
int i, j, min;
ElemType tmp;

for (i = 0; i < length - 1; ++i) // 需要n-1趟  
{  
    min = i;  

    for (j = i + 1; j < length; ++j)  
    {  
        if (arr[j] < arr[min]) // 每一趟选择元素值最小的下标  
        {  
            min = j;  
        }  
    }  

    if (min != i) // 如果第i趟的Li元素值该趟找到的最小元素值,则交换,以使Li值最小  
    {  
        tmp = arr[i];  
        arr[i] = arr[min];  
        arr[min] = tmp;  
    }  
}  

}

/*
7、堆排序算法
堆的定义如下:n个关键字序列号L[1..n]称为堆,仅当该序列满足:
1)L(i) <= L(2i)且L(i) <= L(2i+1) 或 2)L(i) >= L(2i)且L(i) >= L(2i+1)
满足第一种情况的堆,称为小根堆(小顶堆);
满足第二种情况的堆,称为大根堆(大顶堆)。
*/
void HeapAdjust(ElemType *a,int i,int size) //调整堆
{
int lchild = 2 * i; //i的左孩子节点序号
int rchild = 2 * i + 1; //i的右孩子节点序号
int max = i; //临时变量

if(i <= size / 2)          //如果i是叶节点就不用进行调整   
{  
    if (lchild <= size && a[lchild] > a[max])  
    {  
        max = lchild; // 左孩子比双亲值还大,需要调整  
    }    

    if (rchild <= size && a[rchild] > a[max])  
    {  
        max = rchild;// 右孩子比双亲值还大,需要调整  
    }  

    if (max != i) // 需要调整  
    {  
        ElemType tmp = a[max];  
        a[max] = a[i];  
        a[i] = tmp;  

        HeapAdjust(a, max, size);    //避免调整之后以max为父节点的子树不是堆   
    }  
}          

}

void BuildHeap(ElemType *a,int size) //建立堆
{
for (int i = size / 2; i >= 0; i--) //非叶节点最大序号值为size/2
{
HeapAdjust(a, i, size);
}
}

void HeapSort(ElemType *a, int size) //堆排序
{
BuildHeap(a,size);

for(int i = size - 1; i >= 0; i--)  
{  
    swap(a[0], a[i]);           //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面   
    BuildHeap(a, i-1);        //将余下元素重新建立为大顶堆   
    HeapAdjust(a,1,i-1);      //重新调整堆顶节点成为大顶堆  
}  

}

void Display(ElemType arr[], int length)
{
for ( int i = 0; i < length; ++i )
{
cout << arr[i] << " ";
}

cout << endl;  

}
int main()
{
ElemType arr[] = {2, 1, 5, 3, 4, 0, 6, 9, -1, 4, 12};

//InsertSort(arr, sizeof(arr) / sizeof(ElemType));  
//BinaryInsertSort(arr, sizeof(arr) / sizeof(ElemType));  
//ShellSort(arr, sizeof(arr) / sizeof(ElemType));  
//BubbleSort(arr, sizeof(arr) / sizeof(ElemType));  
//QuickSort(arr, 0,  sizeof(arr) / sizeof(ElemType) - 1);  
HeapSort(arr, sizeof(arr) / sizeof(ElemType));  
Display(arr, sizeof(arr) / sizeof(ElemType));  

return 0;  

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • //联系人:石虎QQ: 1224614774昵称:嗡嘛呢叭咪哄 //常用的排序算法 细节请看:http://blo...
    石虎132阅读 396评论 0 4
  • 本文仅作为个人学习排序算法的参考笔记,若想详细了解学习,请前往 http://blog.csdn.net/han_...
    biubiu15阅读 548评论 0 0
  • 总结一下常见的排序算法。 排序分内排序和外排序。内排序:指在排序期间数据对象全部存放在内存的排序。外排序:指在排序...
    jiangliang阅读 1,310评论 0 1
  • 一、常见排序算法一览: 时间复杂度: 是一个函数,它定量描述了该算法的运行时间。 空间复杂度:一个算法在运行过程中...
    夕望有你阅读 874评论 0 0
  • 午后的天变成铅色 怎么眺也看不到清晨的流云 午睡醒来 你的脸印着红红的褶纹 怕是在梦里的一生一世吧 我想吻你的腮了...
    Harvest收获阅读 449评论 90 89