数据结构复习:排序——希尔排序

希尔排序是怎么来的?

        我们此前学习了插入排序,发现他交换数据的次数仍然很多,想要降低他的次数需要将数列变得部分有序,我们可以将原来的数列分为多组,每组都进行一次插入排序,这样总体的数列就是部分有序的了。最后再将已经部分有序的数列最后进行一次插入排序时可以降低它的交换次数。 

  • 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
  • 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;

如何实现

希尔排序是把序列按下标的一定增量分组,对每组使用直接插入排序算法排序。随着增量的逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个序列恰好被分为一组(也就是最后进行一次直接插入排序),算法便终止。它每一趟的操作并没有像冒泡,选择排序一样直接对某一个数进行归位。它是在将整个数列变得部分有序,最后进行一次插入排序。

基本思想

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。

基本过程

首先,希尔排序算法效率增量序列的取值有关。这是一个很复杂的数学问题,同样,对于不同的数据,采用不同的增量也会导致算法效率的不同,这一问题还没有有效的解决。

  1. 我们在取增量时一般采用len/2。缩小增量为inc/2的形式。
  2. 外层循环:缩小增量。即控制从较少的元素分为一组插入排序到较多的元素一组插入排序。
  3. 里层循环:插入排序。把增量为Inc的一组数进行插入排序。当arr[i+Inc]<arr[i]时就对调两个元素下标

时间复杂度

  • 最优时间复杂度:O(n ^ (1.3) )
  • 最差时间复杂度:O(n ^ 2)
  • 稳定性:不稳定

 代码实现

Python

import numpy as np


# 请把希尔排序算法补充完整
def shellSort(arr):
    inc =len(arr)//2
    while inc>=1:
        for i in range (0,len(arr)-inc):
            while i >=0:
                if arr[i+inc]<arr[i]:
                    arr[i+inc],arr[i]=arr[i],arr[i+inc]
                    i-=inc
                else: break
        inc //= 2
    return arr


if __name__ == '__main__':
    nums = np.random.permutation(20)
    shellSort(nums)
    print(nums)

 java

import java.util.LinkedList;

class shell_sort {
     int[] datas;//待排序数据

     public shell_sort(int[] datas) {
         this.datas = datas;
     }

     public void sort() {
         int temp;//temp用来保存交换的数
         int inc=this.datas.length/2;//排序增量
         while (inc>=1){//inc 等于1时是最后一次直接插入排序
             for(int i=0;i< this.datas.length-inc;i++){
                 while (i>=0){
                     if (this.datas[i+inc]<this.datas[i]){
                         temp=this.datas[i];
                         this.datas[i]=this.datas[i+inc];
                         this.datas[i+inc]=temp;
                         i-=inc;
                     }
                     else break;
                 }
             }
            inc=inc/2;
         }
     }
    public void print(){
        LinkedList list =new LinkedList();
        for(int i=0;i< datas.length;i++){
            list.add(datas[i]);
        }
        System.out.println(list);
    }
    public static class SortTest{
        public static void main(String[] args) {
                test_shellsort();
        }
        public static void test_shellsort(){
            int[] arrays={9,1,5,8,3,7,4,6,2,0};//待排序数组
            shell_sort shellSort = new shell_sort(arrays);
            shellSort.sort();
            shellSort.print();
        }
    }
 }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值