一个特殊序列的排序问题
有一个关于排序的问题:
类似于在学校时的站队:在一次排好队后,老师可能是这么跟大家说的:“记住自己前面的是谁,以后按这个顺序排!”
抽象出来就是,比如有一个队列[1,2,3],在排序的时候,1和2比较可以知道1在2前面,2和3比较也可以知道2在3前面,但1和3比较是不知道结果的。这样一来,我们的排序算法/比较器(还是不能用比较器了?)该怎么写呢?

解决方案 »

  1.   

    假如扩展一下,序列是[A,B1,B2,C1,C2]
    这里,只知道:A<B1,A<B1,B2<C1,B2<C2
    也就是说排序排成:[A,B2,C1,C2,B1]
    或者[A,B2,B1,C1,C2]
    或者[A,B1,B2,C1,C2]
    或者[A,B1,B2,C2,C1]
    都是可以的。这就有点像树了
      

  2.   

    假如扩展一下,序列是[A,B1,B2,C1,C2]
    这里,只知道:A <B1,A <B2,B2 <C1,B2 <C2
    也就是说排序排成:[A,B2,C1,C2,B1]
    或者[A,B2,B1,C1,C2]
    或者[A,B1,B2,C1,C2]
    或者[A,B1,B2,C2,C1]
    都是可以的。这就有点像树了
      

  3.   

    可以用TreeMap来做。k为每一元素的编号,value为元素。
      

  4.   

    不对了,k为元素,value是序号.排序时,根据元素可以从Map中求得其序号,比较序号就可以了。
      

  5.   

    可能表达得不是很清楚?
    用代码说话:
    class Item implements Comparable<Item>{
    private int i;

    public Item(int i) {
    super();
    this.i = i;
    }

    public int getI() {
    return i;
    } public void setI(int i) {
    this.i = i;
    } @Override
    public int compareTo(Item o) {
    int c = i - o.i;
    if (c == 1 || c == -1) {
    return c;


    return 0;
    }

    @Override
    public String toString() {
    return String.valueOf(i);
    }
    }那问题就是:给定一个Item的集合,如何得到一个该集合的序列,使得序列中任意元素都小于等于(compareTo返回结果小于等于零)它后面的元素。
      

  6.   

    有人明白bigbug9002想说的意思吗?我的疑问:
    1)为什么是TreeMap?
    2)"根据元素可以从Map中求得其序号,比较序号就可以了。" +  "无论如何你得有一个预设的序列吧。也就是说每一个元素都有一个唯一的序号于之对应。"
    => 原来序列就是有序的?? 我上面给出是有序的是为了说明要求啊
      

  7.   

    你既然实现了Comparable了,可以直接用Arrays.sort和Collections.sort了
      

  8.   

    说得太费劲了。代码如下:
    package test;import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;public class Sorter {
    public static void main(String[] args) {
    List<Item> list = new ArrayList<Item>();
    for (int i = 0; i < 10; i++) {

    list.add(new Item((int) (Math.random()*12)));
    }
    Collections.shuffle(list);

    System.out.println("排序前:" + Arrays.toString(list.toArray()));

    sort(list);

    System.out.println("排序后:" + Arrays.toString(list.toArray()));
    } private static void sort(List<Item> list) {
    // TODO Auto-generated method stub

    }
    }package test;public class Item {
    private int i;

    public Item(int i) {
    super();
    this.i = i;
    }

    public int compareTo(Item o) {
    int c = i - o.i;
    if (c == 1 || c == -1) {
    return c;


    return 0;
    }

    @Override
    public String toString() {
    return String.valueOf(i);
    }
    }
    如上代码,只允许在Sorter的sort方法内添加代码的限制下,如何能让sort后list有顺序?
      

  9.   

    补充说明:1) 为了不造成“你既然实现了Comparable了,可以直接用Arrays.sort和Collections.sort了”的误解,我把原来实现的comparable接口去掉了2) Item中i不可访问,意思是已经提供了比较方法了。不要尝试用反射之类的方法来重写比较方法3) 给出一个简单的实现方法:在冒泡排序的基础上再加一重循环就可以了,时间复杂度为O(N*N*N)
      

  10.   

    如果这个序列能像arraylist一样可以遍历的话,这不就是一个排序算法的实现吗?只不过比较时调用Items的compareTo方法而已,有什么区别?
      

  11.   

    mport java.util.*;
    class Item implements Comparable<Item>{
        private int i;
        
        public Item(int i) {
            super();
            this.i = i;
        }
        
        public int getI() {
            return i;
        }    public void setI(int i) {
            this.i = i;
        }    @Override
        public int compareTo(Item o) {
            int c = i - o.i;
            if (c == 1 || c == -1) {
                return c;
            } 
            
            return 0;
        }
        
        @Override
        public String toString() {
            return String.valueOf(i);
        }
    }
    public class Sorter{
    private HashMap<Item,Integer> originalList=new HashMap<Item,Integer>();
    Sorter(List<Item> myList){
    for(int i=0;i<myList.size();i++){
    originalList.put(myList.get(i),i);
    }
    }
    public  void sort(List<Item> myList){
    Collections.sort(myList,new comparator());
    }
    public class comparator implements Comparator<Item>{
    public int compare(Item i1,Item i2){
    return originalList.get(i1)-originalList.get(i2);
    }
    public boolean equals(Object o){
    return false;
    }
    }
    public static void main(String[] args){
    Random rand=new Random();
    List<Item> list = new ArrayList<Item>();
            for (int i = 0; i < 10; i++) {
       
                list.add(new Item(rand.nextInt(10)));
            }
            
            Sorter mySorter=new Sorter(list);
            System.out.println("排序之前");
    System.out.println(list);
            
            Collections.shuffle(list);
            for(int i=0;i<3;i++){
             System.out.println(list.remove(i)+"被删除了");
            }
            mySorter.sort(list);
    System.out.println("排序之后");
    System.out.println(list);
    }
    }
    F:\java>java Sorter
    排序之前
    [3, 1, 6, 3, 4, 5, 7, 5, 6, 2]
    5被删除了
    2被删除了
    5被删除了
    排序之后
    [3, 1, 6, 3, 4, 7, 6]
      

  12.   

    楼主的意思大概明白了:
    就是:
    有若干集合 A B C
    其中
    A={a}
    B={b1, b2}
    C={c1, c2}
    b1,b2之间没有明确的顺序,同样c1,c2也没有明确的顺序
    已知排列 A->B->C
    现在要将 集合中的所有元素按上面A->B->C的顺序填回去。
    那么:
    可以先将ABC排序,然后再对每个集合求出其所有元素可能的排列,最后把两个结果并在一起。
      

  13.   

    对了,由于没有给出 b1和c1,c2直接的关系,那么还有种可能是
    A={a} 
    B={b2} 
    C={b1, c1, c2} 
    b1,b2之间没有明确的顺序,同样b1,c1,c2也没有明确的顺序 
    排列 A->B->C 
      

  14.   

    Sign~难道我说的真有那么不清楚吗?LS的基本有两个误区:
    1) 把我的例子里的compareTo方法直接等同于基本/标准的比较方法了。
    我已经明确说了,这是一个特殊的排序问题。一般来说,compareTo返回0指的是两者相同/等价;但我这里返回0可能是没法在两者间比较。2)我给的123,ABC例子仅仅作为一个说明方法。能不能把Item做为一个对象来看待啊(而且对象里面的东西是没有提供getter&setter的)
      

  15.   

    有两点我表达得辞不达意的地方:
    1)代码里public int compareTo(Item o) {
            int c = i - o.i;
            if (c == 1 || c == -1) {
                return c;
            } 
            
            return 0;
        }
    这个方法只能用来作排序后是自然序列的比较方法。因为如果中间漏掉一些数据的话它返回的结果就不对了。而且这个方法没有考虑两者相等的情况(那就只考虑没有相等的情况吧)2)关于上面提到的“简单实现”
     也就是说我自己已有一个办法去实现,如下:
    private static void sort(List<Item> list) {
    for (int i = 0; i < list.size()-1; i++) {
    for (int j = 0; j < list.size()-1; j++) {
    for (int k = j; k < list.size(); k++) {
    if (list.get(j).compareTo(list.get(k)) > 0) {
    Item temp = list.get(j);
    list.set(j, list.get(k));
    list.set(k, temp);
    }
    }
    }
    }

    }很明显,这里用了三层循环,而且里面的两层循环就是大家所熟悉的冒泡排序~
    以上,我觉得已经尽可能的表达清楚了。如果还是不明白,那只能说明我表达有限,没有办法了~
      

  16.   

    dz007的想法有点实际内容了!实际上这种方法我也想过,代码如下:
    private static void sort(List<Item> list) {
    List<Item> ll = new LinkedList<Item>();
    ll.add(list.remove(0));

    for (int j = 0, size = list.size(); j < size && list.size() > 0; j++) {
    int pre = -1, next = -1;
    for (int k = 0; k < list.size(); k++) {
    if (list.get(k).compareTo(ll.get(0)) < 0) {
    pre = k;
    } else if (list.get(k).compareTo(ll.get(ll.size()-1)) > 0) {
    next = k;
    }
    }

    if (pre >= 0) {
    ll.add(0, list.get(pre));
    }
    if (next >= 0) {
    ll.add(list.get(next));
    }

    if (pre >= 0 && next >= 0) {
    list.remove(pre > next ? pre : next);
    list.remove(pre > next ? next : pre);
    } else {
    if (pre >= 0) {
    list.remove(pre);
    }
    if (next >= 0) {
    list.remove(next);
    }
    }
    }

    list.addAll(ll);
    }
    这对于完全有序的集合是对的。
    但是类似于[1,2,3,5,6,7]这种集合就出错了~注:我提到的什么例子,都是以它的有序序列列出来的;排序前可能是任意顺序的。
    [1,2,3,5,6,7]的另一种顺序是[5,6,7,1,2,3]
      

  17.   

    哈,打字时突然想到一种递归调用:
    在上面的
    list.addAll(ll);
    前面加上:
    if (!list.isEmpty()) {
    sort(list);
    }
    就可以了我再想想如果有相等元素的情况就OK了~
      

  18.   

    就用冒泡排序法就可以,二重循环即可,改了一下你的程序
    private static void sort(List list) {
    for (int i = 0; i < list.size() - 1; i++) {
    for (int j = i+1; j < list.size(); j++) { if ((list.get(j)).compareTo( list.get(i) ) < 0 ) {
    Item temp = list.get(j);
    list.set(j, list.get(i));
    list.set(i, temp);
    }
    }
    } }
      

  19.   


    不要想当然好吧你明白我的要求&试过你的代码?