链表问题

时间:2015-06-03 11:42:23

标签: java

我对RationalSet类的主要方法有疑问,这是RationalNode的链接列表。在这个方法中,我创建了两个列表和两个节点,第一个列表有两个节点,但第二个只有一个,但是当我这个时,第二个有两个节点。我不知道为什么。

这是我的代码:

RationalSet

class RationalSet {
    static Scanner keyboard = new Scanner(System.in).useLocale(Locale.US);

    RationalNode first, previousIP, IP, previousAux;
    int size;

    public RationalSet() {
        first = null;
        previousIP = null;
        IP = null;
        size = 0;
    }

    public int cardinal() {
        return size;
    }

    private boolean isEmpty() {
        return first == null;
    }

    public boolean belongs(RationalNode r) {
        return position(r) != null;
    }

    public void insert(RationalNode r) {
        if (isEmpty()) {
            first = r;
            previousIP = first;
            IP = previousIP.next;
            size++;
        } else if (!belongs(r)) {
            previousIP.next = r;
            previousIP = previousIP.next;
            IP = previousIP.next;
            size++;
        }
    }

    public void delete(RationalNode r) {
        if (!isEmpty()) {
            RationalNode aux = position(r);
            if (aux != null) {
                if (aux == first)
                    first = aux.next; // I'm comparing references
                else
                    previousAux.next = aux.next;
                size--;
            }
        }
    }

    private RationalNode position(RationalNode r) {
        RationalNode aux = first;
        while (aux != null && !aux.equals(r)) {
            previousAux = aux;
            aux = aux.next;
        }
        return (aux == null) ? null : aux;
    }

    public boolean exists(RationalSet c) {
        RationalNode aux = c.first;
        while (aux != IP && belongs(aux))
            aux = aux.next;
        return aux == null;
    }

    public boolean equals(RationalSet c) {
        if (c.cardinal() != cardinal())
            return false;
        if (this == c || (isEmpty() && c.isEmpty()))
            return true;
        return exists(c) && c.exists(this);
    }

    public String toString() {
        String s = "{";
        for (RationalNode aux = first; aux != null; aux = aux.next)
            s += aux.toString() + ", ";
        return s + "}";
    }

    public Object clone() {
        RationalSet c = new RationalSet();
        for (RationalNode aux = first; aux != null; aux = aux.next)
            c.insert((RationalNode) aux.clone());
        return (Object) c;
    }

    public RationalSet union(RationalSet c) {
        RationalSet u = (RationalSet) this.clone();
        for (RationalNode aux = c.first; aux != null; aux = aux.next)
            u.insert(aux);
        return u;
    }

    public RationalSet intersection(RationalSet c) {
        RationalSet in = new RationalSet();
        for (RationalNode aux = first; aux != null; aux = aux.next)
            if (c.belongs(aux))
                in.insert(aux);
        return in;
    }

    public static void main(String[] args) {
        RationalSet c1 = new RationalSet(), 
                    c2 = new RationalSet();
        Rational r1 = new Rational(-2, 3),
                 r2 = new Rational(1, 1);
        RationalNode n1 = new RationalNode(r1), 
                     n2 = new RationalNode(r2);
        c1.insert(n1);
        c1.insert(n2);

        c2.insert(n1);

        RationalSet u = c1.union(c2);

        System.out.println(u);
        System.out.println(c1.intersection(c2));
    }
}

RationalNode

class RationalNode {
    Rational rational;
    RationalNode next;

    public RationalNode(Rational r) {
        rational = r;
        next = null;
    }

    public RationalNode(Rational r, RationalNode s) {
        rational = r;
        next = s;
    }

    public boolean equals(Object obj) {
        if (obj instanceof RationalNode) {
            RationalNode a = (RationalNode) obj;
            if (this == a)
                return true;
            return (rational == null) ? false : rational.equals(a.rational);
        } else
            return false;
    }

    public String toString() {
        return rational.toString();
    }

    public Object clone() {
        return (Object) new RationalNode((Rational) rational.clone());
    }
}

理性

class Rational {
    static Scanner keyboard = new Scanner(System.in).useLocale(Locale.US);

    private long num, den;

    public Rational(long n, long d) {
        num = n;
        den = d;
        simplify();
    }

    Rational(Scanner t) {
        System.out.print("Give me a numerator: ");
        num = t.nextInt();
        System.out.print("Give me a denominator: ");
        den = t.nextInt();
        simplify();
    }

    public static Rational read(Scanner input) {
        System.out.print("Numerator: ");
        long n = input.nextLong();
        System.out.print("Denominator: ");
        long d = input.nextLong();
        return new Rational(n, d);
    }

    public long num() {
        return num;
    }

    public long den() {
        return den;
    }

    public Rational inverse() {
        return new Rational(den, num);
    }

    public static Rational inverse(Rational r) {
        return new Rational(r.den(), r.num);
    }

    public void autoInverse() {
        long aux = num;
        num = den;
        den = aux;
    }

    public Rational opposite() {
        return new Rational(-num, den);
    }

    public Rational multiply(Rational r) {
        return new Rational(r.num * num, den * r.den);
    }

    public Rational divide(Rational r) {
        return multiply(r.inverse());
    }

    public Rational sum(Rational r) {
        return new Rational(num * r.den + den * r.num, den * r.den);
    }

    public Rational deduct(Rational r) {
        return sum(r.opposite());
    }

    public void simplify() {
        if (num == 0 && den != 0)
            den = 1;
        else if (num != 0 && den == 0)
            num = (num >= 0) ? 1 : -1;
        else if (num != 0 && den != 0) {
            long numAbs = Math.abs(num), denAbs = Math.abs(den);
            long lcd = lcd(numAbs, denAbs);
            long signDen = den / denAbs;
            num = signDen * (num / lcd);
            den = signDen * (den / lcd);
        }
    }

    private static long lcd(long a, long b) {
        if (a == b)
            return a;
        else if (a > b)
            return lcd(a - b, b);
        else
            return lcd(a, b - a);
    }

    public String toString() {
        return num + "/" + den;
    }

    public boolean equals(Rational r) {
        return r.num == num && r.den == den;
    }

    public Object clone() {
        return (Object) new Rational(num, den);
    }

    public static void main(String a[]) {
        Rational r1 = new Rational(23, -38), r2 = new Rational(4, 2);
        System.out.println(r1.toString() + " " + r1.num + " / " + r1.den);
        r1 = r1.inverse();
        System.out.println(r1 + " " + r1.num + " / " + r1.den);
        r1 = inverse(r1);
        System.out.println(r1 + " " + r1.num + " / " + r1.den);
        r1.autoInverse();
        System.out.println(r1 + " " + r1.num + " / " + r1.den);
        r1 = new Rational(23, -38);
        Rational r3 = new Rational(23, -38);
        System.out.println((r1 == r3) + "  " + r1.equals(r3));
    }
}

1 个答案:

答案 0 :(得分:0)

您不应在set之外创建节点。当你这样做

c1.insert(n1);

首先执行此代码

if (isEmpty()) {
    first = r;
    previousIP = first;
    IP = previousIP.next;
    size++;
}

保存在firstpreviousIP当前节点中,该节点也由n1存储。但是当你稍后执行时

c1.insert(n2);

因为c1不再为空else部分已执行

} else if (!belongs(r)) {
    previousIP.next = r;
    previousIP = previousIP.next;
    IP = previousIP.next;
    size++;
}

previousIP.next设置为r,因为previous与参考n1r保持相同的对象为n2,您实际上是在设置n1.next=n2

最后,您要使用

n1添加到第二套n2
c2.insert(n1);

但这意味着您要添加已在内部指向n1的{​​{1}}。这就是n2c1似乎包含相同结构的原因。

您应该做的是以内部创建自己的独立c2的方式重写您的insert方法。因此,您的代码不应该专注于接受RationalNodes,而应关注RationalNodes

Rationals

您还需要重新设计处理public void insert(Rational r) { if (isEmpty()) { first = new RationalNode(r);//changed previousIP = first; IP = previousIP.next; size++; } else if (!belongs(r)) { previousIP.next = new RationalNode(r);//changed previousIP = previousIP.next; IP = previousIP.next; size++; } } 以处理RationalNode的其余代码。

顺便说一句,你可以在Rational中制作RationalNode私人内部课程。这种方式更明确地说,该类的实例应仅由RationalSet创建,并且必须属于其中一个实例。