C++插入排序之二路插入(环与非环的比较)

#include <iostream>
using namespace std;
void Grial(int a[],int n)
{
    int i,j;
    i=j=0;
    int b[n];
    b[0]=a[i];
    int k;
    for(k=1;k<n;k++)
    {
        if(b[i]<a[k])
            {
                b[i+1]=a[k];
                i++;
            }
        else if(b[j]>a[k])
            {
                b[(j-1+n)%n]=a[k];
                j=(j-1+n)%n;
            }
         else
            {
                i++;
                int m;
                for(m = i;b[m-1]>a[k];m--)
                {
                    b[(m+n)%n] = b[(m-1+n)%n];
                }
                b[(m+n)%n]=a[k];
            }
    }
    i++;
    k = 0;
    do
    {
        a[k++]=b[(i)%n];
        i++;
    }while(i%n!=j);
}
int main()
{
    int a[]={10,4,2,5,88,1,23};
    Grial(a,7);
    for(int i=0;i<7;i++)
    {
        cout<<a[i]<<"\t";
    }
    cout<<endl;
    return 0;
}
//心得:此处的2路插入排序,虽然一定程度上减少了插入排序的时间效率,也就是移动数据的消耗,但是如果这是一个逆序的数组,
//那么它的移动次数一样很大,于是我想了一种如下的方法,不采用循环移动,我只比较一次,然后再一边移动,就是没有从0下标到n
//下标的移动,再使用一个平衡因子flags会使插入更加的均衡,这样会一定程度上减少特殊率,请看我的分析代码.

//下面是我自己觉得循环的搞是有点麻烦,并且当数字超出0下标时移动的位数就会很多,下面是我的方法,
//没有循环移动,而是与b[0]比较,如果比b[0]小,在比较len(i)跟len(J),如果左边的大于右边,我则将它插入右边.反则类似。
#include <iostream>
using namespace std;
//2路插入排序.
void Grial(int a[],int n)
{
    int  i;
    int j;
    int b[n];//新开辟的空间用来排序.
    b[0]=a[0];
    i=1;
    j=n-1;
    int k;
    for(k=1;k<n;k++)
    {
        int flag = i>(n-j)?1:-1;//比较左边的长度与右边的长度,如果左边的大,则flag记1,else记-1.
        if(a[k]>b[i-1])
        {
            b[i]=a[k];
            i++;
        }
        else if(a[k]<b[0] && flag == 1)//a[k]<b[0],我们可以将a[k]插入b[0]左边,或者j-n的位置,
                                                                        //使b数组中两边的长度几乎一致.。
        {
                if(j==n-1)
                    {
                    b[j]=a[k];
                        j--;
                        continue;
                    }
                    for(int m = j;m<n;m++)
                    {
                        if(a[k]>b[m+1])
                            b[m]=b[m+1];
                        else
                          {
                            b[m]=a[k];
                            break;
                            }
                    }
                j--;
        }
        else
        {
            int m;
            for(m = i; b[m-1]>a[k] && m>0;m--)
            {
                    b[m]=b[m-1];
            }
            b[m]=a[k];
            i++;
        }
    }
    j = i;
    k=0;
    do{
            a[k++]=b[(i+n)%n];
            i++;
        }while((i%n)!=j);
}
int main()
{
    int a[]={2,4,77,3,1,6,3,10,8,-1};
    Grial(a,10);
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<"\t";
    }
    cout<<endl;
    return 0;
}
时间: 2024-12-29 17:11:29

C++插入排序之二路插入(环与非环的比较)的相关文章

insertion-sort-list——链表、插入排序、链表插入

Sort a linked list using insertion sort. PS:需要考虑left为head且只有一个数时,此时left->==NULL,若right<left则应更新left. 比较p->next->val与right->val以此来避免需要记录preNode 1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *nex

【插入排序】直接,折半,二路,希尔

插入排序 给出一下四种方法: 直接插入排序,折半插入排序,二路插入排序,希尔插入排序 代码实现: #include<iostream> using namespace std; #define size 21 typedef int Sqlist[size]; void SInsertSort(Sqlist &L, int n) //直接插入 { cout << "直接插入排序" << endl; for (int i = 2; i <

数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作

AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1). 也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树). 对Avl树进行相关的操作最重要的是要保持Avl树的平衡条件.即对Avl树进行相关的操作后,要进行相应的旋转操作来恢复Avl树的平衡条件. 对Avl树的插入和删除都可以用递归实现,文中也给出了插入的非递归版本,关键在于要用到栈. 代码如下: #inclu

堆的插入、删除和建立操作,堆排序

1.        堆 堆:n个元素序列{k1,k2,...,ki,...,kn},当且仅当满足下列关系时称之为堆: (ki <= k2i,ki <= k2i+1) 或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4,...,n/2) 若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左.右孩子结点的值.由此,若序列{k1,k2,…,kn}是堆,则堆顶元

&lt;离散数学&gt;代数系统——群,半群,环,域,格,布尔代数

------运算的定义及性质 设S是一个非空集合,映射f:Sn->S称为S上的一个n元运算.假设“•”是定义在集合S上的一个二元运算.若: ∀x,y∈S,x•y∈S,则称“•”在S上是封闭的. ∀x,y∈S,x•y=y•x,则称“•”在S上是可交换的. ∀x,y,z∈S,x•(y•z)=(x•y)•z,则称“•”在S上是可结合的. ∀x∈S,x•x=x,则称“•”在S上是幂等的. 设◆和☉是同时定义在S上的两个二元运算,如果 ∀x,y,zs,x☉(y◆z)=(x☉y)◆(x☉z)且y☉(z◆x)

环的定义与性质

环 定义两个运算+,*,在第一个运算上是阿贝尔群,在第二个运算上满足结合和分配律 对环的修饰都是针对第二个运算的 交换环与单位环 交换环:第二个运算具有交换律 单位环:第二个运算具有单位元 零因子 a,b属于环R,但a,b都不为0(第一个运算的单位元,也是第二个运算的零元),若a*b = 0,则说a.b分别是零因子 整环 可 大专栏  环的定义与性质交换且无零因子的环 除环 有单位元且每个非零元都有逆元的环 除环若关于第二个运算满足交换律,则升级为域 环的性质 2条定理 定理一 a0 = 0a

AsyncTask类插入数据到服务器与接口回调

////////////////2016/04/21///////////////////// //////////////by XBW/////////////////////////// ///////////环境  api22 eclipse ///////////// 搞了这么久终于弄好了接口,之前都是一个人在做项目,自己随心所欲的写代码,想怎么写就怎么写,到了团队呢,这接口那接口,各种类,各种枚举,各种内部类,抽象类,单例懒汉,单例饿汉的,也算学了不少东西, 我做的是把数据插入到数据库

判断单链表是否有环以及环的连接点

给定一个单链表,只给出头指针h: 1.如何判断是否存在环? 2.如何知道环的长度? 3.如何找出环的连接点在哪里? 4.带环链表的长度是多少? 解法: 1.对于问题1,使用追赶的方法,设定两个指针slow.fast,从头指针开始,每次分别前进1步.2步.如存在环,则两者相遇:如不存在环,fast遇到NULL退出. 2.对于问题2,记录下问题1的碰撞点p,slow.fast从该点开始,再次碰撞所走过的操作数就是环的长度s. 3.问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分

oracle用sql 语句如何向表中插入时间?

有关日期的操作中,更多的是涉及系统当前时间,用sysdate表示即可,如果是插入其他非系统时间的日期类型数据的话,用to_date转换再插入就可以了.例: 1 insert into 表(c_date) values(to_date('20120927 20:09:47','YYYYMMDD HH24:MI:SS')); 另外:有些日期字段中会有一些默认数据,所以to_date还是挺有用的.如: 1 startdate date DEFAULT to_date('2000-01-01','yyy