数据结构算法应用

1.问题: 对一组长度为N的数组,找到其中排序为第K个的数
   回答:采用快速排序的方法
import java.util.*;

public static Comparable select (Comparable[] a, int K)
{
     if(k<0||k>= a.length)
     { throw new IndexOutOfBoundsException("k is out of the bounds!"); }
     Collections.shuffle(a);
     int lo = 0, hi=a.length - 1;
     while(lo < hi)
     {
          int j = partition(a, lo, hi);
          if(k>j) lo = j+1;
          else if (k<j) hi = j-1;
          else return a[j];
     }
     return a[lo];
}


时间复杂度:
最差是二次,但是在前面做了shuffle的情况下,基本可以保证是线性的
N+N/2+N/4+....+1  ~ 2N


2. 问题: Dijkstra提出的“荷兰国旗问题”(The Dutch National Flag Problem)
待排序序列的关键字中有很多重复的值,把数据分成三段,使相同的值在中间,左边的都比其小,右边的都比其大。
比如我们想对所有的学生按照年龄进行排序,按照性别进行排序等,这样每一类别中会有很多的重复的值。理论上,这些重复的值只需要处理一次就行了。但是一般的快速排序会递归进行划分,因为一般的快速排序只是将序列划分为了两部分,小于或者大于等于这两部分。

既然要利用连续、相等的元素不需要再参与排序这个事实,一个直接的想法就是通过划分让相等的元素连续地摆放:

Dijkstra的方法如图:


从左至右扫描数组,维护一个指针lt使得[lo…lt-1]中的元素都比v小,一个指针gt使得所有[gt+1….hi]的元素都大于v,以及一个指针i,使得所有[lt…i-1]的元素都和v相等。元素[i…gt]之间是还没有处理到的元素,i从lo开始,从左至右开始扫描:

· 如果a[i]<v: 交换a[lt]和a[i],lt和i自增

· 如果a[i]>v:交换a[i]和a[gt], gt自减

· 如果a[i]=v: i自增


代码:
public static void sort(Comparable[] a)
{
     Collections.shuffle(a);
     sort(a, 0, a.length-1);
}

private static void sort(Comparable[] a, int lo, int hi)
{
//小序列,采用插入排序算法
     if(hi - lo <= CUTOFF - 1)
     {
          insertionSort(a, int lo, int hi);
          return;
     }
     int lt = lo, gt = hi;
     Comparable v = a[lo];
     int i = lo;
     while (i <= gt)
     {
          int cmp = a[i].compareTo(v);
          if (cmp < 0) {exch(a, i++, lt++); }
          else if(cmp > 0) {exch(a, i, gt--); }
          else i++;
     }
}

private static void insertionSort(Comparable[] a, int lo, int hi)
{
     for(int i = lo; i <= hi; i++)
     {     
          for(int j = i; j>lo&&less(a, j, j-1); j--)
               exch(a, j, j-1);
     }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值