数据结构之常用c语言排序算法

#include <iostream>
#include <string.h>
using namespace std;

#define NUM 16
#define MAX 100
#define MAX_LINE_NUMBER 16
int list[NUM*7]={0};
int merge_list[NUM*10]={0};
int merge_link[NUM*10]={0};

void init();
void init_list(int);
void out(int[],int ,int);
void swap(int,int);

//1. 直接插入排序
void insert_sort(int len)
{
    int insertNum;
    for (int i = 0; i < len; ++i) {
        insertNum=list[i];//待插入元素
        int j=i;
        //寻找插入位置
        while(j>0 && insertNum < list[j-1])
        {
            list[j]=list[j-1];
            j--;
        }
        list[j]=insertNum;
    }
}
//2. 二分插入排序
void binary_insert_sort(int len)
{
    int middle=-1;
    for (int i = 0; i < len; ++i) {
        int insertNumber=list[i];//待插入元素
        int left=0;
        int right=i-1;
        while(left <= right)//二分法寻找插入位置
        {
            middle=(left+right)/2;
            if(insertNumber > list[middle])
                left=middle+1;
            else
                right=middle-1;
        }
        for (int j = i; j >left; j--) {
            list[j]=list[j-1];
        }
        list[left]=insertNumber;
    }
}

//3. 希尔排序
void shell_sort(int len)
{
    int insertNum=-1;
    int gap=len/2;//初始化增量
    while(gap)//当gap>=1
    {
        for (int i = gap; i < len; ++i) {//对gap间隔子序列进行插入排序

            insertNum=list[i];//待插入元素
            int j=i;
            while(j>=gap && insertNum < list[j-gap])//寻找插入位置
            {
                list[j]=list[j-gap];
                j -=gap;
            }
            list[j]=insertNum;//插入
        }
        gap=gap/2;//缩小增量
    }
}
//4. 直接选择排序
void select_sort(int len)
{
    int k=-1;
    for (int i = 0; i < len; i++) {
        k=i;
        for (int j = i+1; j < len; j++) {//找最小元素
            if(list[j] < list[k])
            {
                k=j;
            }
        }
        swap(i,k);//将最小元素放入i位置
    }
}
//5. 堆排序
//堆的建立或调整
void heap_build(int current,int last)
{
    int child=2*current+1;//child为current的子女位置
    int temp=list[current];//暂存子root节点
    while(child<=last)//判断是否到最后结尾
    {
        if(child<last && list[child] <list[child+1])
        {
            child++;//让child指向两子女中的最大值
        }

        if(temp >= list[child])
            break;//temp的关键码大则不做调整
        else{
            //否则子女中的大则上移
            list[current]=list[child];
            current=child;
            child=2*child+1;
        }
    }
    list[current]=temp;//temp中暂存的元素放到合适位置
}
void heap_sort(int len)
{
    //建立堆
    for (int i = (len-2)/2; i >=0 ; i--) {
        heap_build(i,len-1);
    }
    //不断调整为最大堆
    for (int i = len-1; i >0; i--) {
        swap(0,i);
        heap_build(0,i-1);
    }
}

//6. 冒泡排序
/**
 * 优化冒泡排序 附上解释
 * 一次优化。我们可以想到这种极端情况:array本身就是排序好的,但是依照如上算法,我们仍然要遍历n平方/2次。原因在于,我们没有机制检查数组是否是排序好的。
 * 解决办法就是加入标识项,如果发现一次内层循环没有经过任何交换,则说明array已经排序完毕,需要直接跳出循环。
 */
void bubble_sort(int len)
{
    for (int i=0;i<len;i++)
    {
        bool sorted = true;//考虑有序,减少趟数
        for (int j = i+1; j < len; ++j) {
            if(list[i] > list[j])
            {
                int temp=list[i];
                list[i]=list[j];
                list[j]=temp;
                sorted= false;//考虑有序,减少趟数
            }
        }
        //如果上一轮冒泡排序已经全部有序 即flag!=false,则直接退出,不用进行下一轮冒泡循环,提高效率,否则数组已经有序了,他还会继续冒泡循环
        if (sorted) {
            break;
        }

    }
}
void bubble_sort_simple(int len)
{
    for (int i=0;i<len;i++)
    {
        for (int j = i+1; j < len; ++j) {
            if(list[i] > list[j])
            {
                swap(i,j);
            }
        }
    }
}
//7. Shaker排序
void shaker_sort(int len)
{
    int i=0,shift=0;
    int left=0;
    int right=len-1;
    while(left <right)
    {
        for (i = left; i<right;i++) {//向右进行气泡排序
            if(list[i] >list[i+1])
            {
                swap(i,i+1);
                shift=i;
            }
        }
        right=shift;
        for (i = right; i >left; i--) {//向左进行气泡排序
            if(list[i] <list[i-1])
            {
                swap(i,i-1);
                shift=i;
            }
        }
        left=shift;
    }
}
//8. 快速排序
void quick_sort(int left,int right)
{
    int i=left;
    int j=right;
    int pivot=list[left];//基数
    while(i<j)
    {
        while(i<j && list[j] >= pivot) j--;//找到比基数小的元素
        if(i<j) swap(i,j);

        while (i<j && list[i] <=pivot) i++;//找到比基数大的元素
        if(i<j) swap(i,j);
    }
    if(i!=left)
    {
        quick_sort(left,i-1);
    }
    if(j!=right)
    {
        quick_sort(j+1,right);
    }
}
//9. 归并排序
//具体方法:以merger_link[]提供链表功能。merger_link[i]对应在有序子序列中
//merger_list[i]后一个结点在原merger_list[]中的下标;
//merger_link[0]总是表示有序子序列开始的结点在merge_list[]中的下标;
//st1,st2为两个有序序列的第一个结点;
//将他们归并,并返回其第一个结点的下标,即merger_link[0]
int list_merge(int st1,int st2)
{
    int k=0;
    int i=st1,j=st2;
    while(i && j)//当两序列未检测完
    {
        if(merge_list[i] <= merge_list[j])
        {
            //将merge_list[i]和merge_list[j]中小的连接到merger_link[k]
            merge_link[k]=i;
            k=i;
            i=merge_link[i];
        }else{
            merge_link[k]=j;
            k=j;
            j=merge_link[j];
        }
    }
    //将剩余未检测完的merge_list[]连接到merger_link[k]后
    if(!i)
        merge_link[k]=j;
    else
        merge_link[k]=i;

    return merge_link[0];
}
int merge_sort(int left,int right)
{
    if(left>=right)
        return left;
    int middle=(left+right)/2;
    //对左右两个子序列进行归并
    int st1=merge_sort(left,middle);
    int st2=merge_sort(middle+1,right);
    return list_merge(st1,st2);
}

//10. 计数排序
void counting_sort(int len,int max)
{
    int result[NUM]={0}; //临时保存结果
    int* mark=new int[max];  //标记无序表中元素
    memset(mark,0,max*sizeof(int));
    for (int i = 0; i < len; ++i) {
        mark[list[i]]++; //统计元素出现次数
    }
    for (int i = 1; i < max; ++i) {
        mark[i] +=mark[i-1];//计算元素在有序表中位置
    }
    for (int i = len-1; i >=0  ; i--) {
        result[mark[list[i]]-1] =list[i];//通过mark[]直接将list[i]有序存入result[]

        mark[list[i]]--;
    }
    delete[] mark;
    //转存到list以便输出结果
    for (int i = 0; i < len; ++i) list[i]=result[i];
}

//数据结构之常用c语言排序算法
int main() {
    init();
    int input;
    while(true)
    {
        cout<<"请选择:";
        cin>>input;
        init_list(input);
        switch (input) {
            case 1: insert_sort(NUM); break;
            case 2: binary_insert_sort(NUM); break;
            case 3:shell_sort(NUM);break;
            case 4:select_sort(NUM);break;
            case 5:heap_sort(NUM);break;
            case 6:bubble_sort(NUM);break;
            case 7:shaker_sort(NUM);break;
            case 8:quick_sort(0,NUM-1);break;
            case 9:merge_sort(1,NUM);break;
            case 10:counting_sort(NUM,MAX);break;
            case 0:exit(0);break;

        }
        cout<<"排序结果:"<<endl;
        if(input !=9) {
            out(list,0,NUM);
        }else{
            int i=merge_link[0];
            int j=0;
            while(i)
            {
                j++;
                cout<<merge_list[i]<<" ";
                i=merge_link[i];
                if(j % MAX_LINE_NUMBER ==0 )
                    cout<<endl;
            }
            cout<<endl;
        }
    }

    return 0;
}

// 初始化界面
void init() {
    cout << endl;
    cout << "		十种常用排序算法(升序)" << endl;
    cout << "   ---------------------------------" << endl;
    cout << "		1. 直接插入排序" << endl;
    cout << "		2. 二分插入排序" << endl;
    cout << "		3. 希尔排序" << endl;
    cout << "		4. 直接选择排序" << endl;
    cout << "		5. 堆排序" << endl;
    cout << "		6. 冒泡排序" << endl;
    cout << "		7. Shaker排序" << endl;
    cout << "		8. 快速排序" << endl;
    cout << "		9. 归并排序" << endl;
    cout << "		10.计数排序" << endl;
    cout << "		0. 退出" << endl;
    cout << "   ---------------------------------" << endl;
}

//初始化无序表
void init_list(int input)
{
    if(input ==0) return ;
    cout<<"待排数列为:"<<endl;
    if(input == 9)
    {
        for(int i=1;i<=NUM;i++)
        {
            merge_list[i]=rand() % MAX;
            merge_link[i]=0;
        }
        out(merge_list,1,NUM);
    }else{
        for (int i = 0; i < NUM; ++i) {
            list[i]=rand()% MAX;
        }
        out(list,0,NUM);
    }
}
//打印输出结果
void out(int result[],int st,int len)
{
    for (int i = st; i < st+len; ++i) {
        cout<<result[i]<<" ";
        if((i+1) % (MAX_LINE_NUMBER+st) == 0)
            cout<<endl;
    }
}
void swap(int i,int j)
{
    int temp=list[i];
    list[i]=list[j];
    list[j]=temp;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值