Java 高级排序,JAVA算法之高级排序

本章介绍两种高级排序,希尔排序和快速排序,这两种排序比之前讲到的简单排序都要快很多;希尔排序大约需要O(N*(logN)2)的时间,快速排序的时间复杂度为(N*logN),这两种算法和我们在讲递归的时候讲到的归并排序不同,不需要大量的辅助存储空间,快速排序是所有通用排序算法中最快的排序算法。

希尔排序:

希尔排序是基于插入排序的,希尔排序在插入排序的基础之上通过加大插入排序元素之间的间隔,并在这些间隔元素之间进行插入排序,使数据实现大跨度的移动,从而使排序更有效率,我们习惯将排序时数据项之间的间隔称为增量,用h来表示,下图表示了十个数据项,以增量为4进行第一趟排序后的结果

AAffA0nNPuCLAAAAAElFTkSuQmCC

通过上面的一趟排序之后我们可以看到元素离他们的最终有序序列位置都很近了,希尔排序就是通过创建这种交错有序的数据项集合,从而提高排序的效率,当上面完成了4增量的排序之后,就可以进行普通的插入排序,这样就比普通的插入排序的效率要高很多。

上面对于有十个数据项的数组初始增量我们设置为4,对于数据项更大的数组我们的初始增量也应该设置得更大,这里我们使用Knuth提出的间隔序列,序列的通项表达式为h=3*h+1,假设我们数据项的个数为100,那么通过Knuth间隔序列1,4,13,40,121,364,1093这里1093大于了我们的数据项1000,所以我们取初始的增量为364然后通过Knuth间隔序列依次减小我们的增量值,最终达到我们想要的一个个排序的效果,接下来我们给出希尔排序的java代码

AAffA0nNPuCLAAAAAElFTkSuQmCCpublic class ArrayShell {    public long[] theArray;    private int nElems;    public ArrayShell(int size) {        this.theArray = new long[size];        this.nElems = 0;

}    public void insert(long value) {

theArray[nElems++] = value;

}    public void shellSort() {        //首先找到初始增量

int h = 1;        int outer, inner;        while (h <= nElems/3) {

h = 3 * h + 1;

}        while (h > 0) {            //以下就是普通的插入排序,只是步长换为h即可

for (outer = h; outer 

inner = outer;                while (inner > h - 1 && temp 

theArray[inner] = theArray[inner - h];

inner -= h;

}

theArray[inner] = temp;

}            //从最大增量一直递减到1做插入排序

h = (h - 1) / 3;

}

}

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

希尔排序中间隔序列互质很重要,他能是每一趟排序更有可能保持前一趟已排序好的效果。

快速排序

快速排序是基于划分算法之上的一种排序算法,首先我们介绍一下划分算法的基本原理划分

划分的基本原理就是把数据分为两组,使关键值大于特定值的数据在一组,使关键值小于特定值的数据在另一组,比如我们日常生活中将家距离办公点15km以内和以外的雇员分为两组。划分算法中我们将两个标记分别指向数组的两头,左边的标记leftPtr ,向右移动,右边的标记 rightPtr,向左移动,当leftPtr遇到比枢纽小的数据项时,继续向右移动,当遇到比枢纽大的数据项时就停下来,同样当rightPtr遇到比枢纽大的数值的时候继续向左移动,遇到比枢纽小的就停下来,然后需要交换这两个数据项。交换之后继续移动指针,重复上面的步骤,知道两个标记的值相等的时候则划分算法完成。

接下来我们看划分算法的java代码

AAffA0nNPuCLAAAAAElFTkSuQmCCclass ArrayPar {    public Long[] theArray;    private int nElems;    public ArrayPar(int max) {

theArray = new Long[max];        this.nElems = 0;

}    public void insert(Long value) {

theArray[nElems] = value;

nElems++;

}    public int partitionIt(int leftPtr, int rightPtr, long pivot) {        while (true) {            //当leftPtr遇到比枢纽小的数据项时,继续向右移动(即 leftPtr++),当遇到比枢纽大的数据项时就停下来

while (leftPtr 

leftPtr++;            //当rightPtr遇到比枢纽大的数据项时,继续向左移动(即 rightPtr--),当遇到比枢纽大的数据项时就停下来

while (rightPtr > leftPtr && theArray[rightPtr] >= pivot)

rightPtr--;            //当leftPtr标记大于等于right标记的时候结束外层循环,否则交换两个标记的数据项

if (leftPtr >= rightPtr)                break;            else

swap(leftPtr, rightPtr);

}        return leftPtr;

}    /**交换数据方法*/

public void swap(int dex1, int dex2) {        long temp = theArray[dex1];

theArray[dex1] = theArray[dex2];

theArray[dex2] = temp;

}

}

AAffA0nNPuCLAAAAAElFTkSuQmCC快速排序

快速排序的执行时间为O(N*logN)级,快速排序是基于划分算法之上的,利用递归的思想的一种排序算法,这里我们选择数组的最右边的元素作为枢纽,在划分算法完成之后,需要在之前的算法的基础上加一步,将枢纽项和右数组的起始项进行位置交换,交换后的枢纽值的顺序就是最终的顺序,然后在利用递归将划分后的左右数组进行上述步骤。首先我们来看看快速排序的java代码

AAffA0nNPuCLAAAAAElFTkSuQmCCclass ArrayPar {    public Long[] theArray;    private int nElems;    public ArrayPar(int max) {

theArray = new Long[max];        this.nElems = 0;

}    public void insert(Long value) {

theArray[nElems] = value;

nElems++;

}    public int partitionIt(int leftPtr, int rightPtr, long pivot) {        int right = rightPtr;        while (true) {            //当leftPtr遇到比枢纽小的数据项时,继续向右移动(即 leftPtr++),当遇到比枢纽大的数据项时就停下来

while (leftPtr 

leftPtr++;            //当rightPtr遇到比枢纽大的数据项时,继续向左移动(即 rightPtr--),当遇到比枢纽大的数据项时就停下来

while (rightPtr > leftPtr && theArray[rightPtr] >= pivot)

rightPtr--;            //当leftPtr标记大于等于right标记的时候结束外层循环,否则交换两个标记的数据项

if (leftPtr >= rightPtr)                break;            else

swap(leftPtr, rightPtr);

}

swap(leftPtr,right);    //最后将当前枢纽数值放入对应的排序位置

return leftPtr;

}    /**

* 交换数据方法     */

public void swap(int dex1, int dex2) {        long temp = theArray[dex1];

theArray[dex1] = theArray[dex2];

theArray[dex2] = temp;

}    /***快速排序的方法*/

public void recQuickSort(int left, int right) {        if (right - left <= 0)  //这里是递归的基值条件,当只有一个数据项的时候结束递归

return;        else {            long pivot = theArray[right];     //选择最右边的数据作为划分的枢纽数据

int partition = partitionIt(left, right, pivot);    //调用划分的算法            //然后将划分好的两部分利用递归的思想进行再次划分排序

recQuickSort(left, partition - 1);

recQuickSort(partition + 1, right);

}

}

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

下图显示了快速排序的过程

AAffA0nNPuCLAAAAAElFTkSuQmCC

上面就是希尔排序算法和快速排序算法的所有内容

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值