Java'da bağlantılı bir listeyi yinelemeli olarak ters çevirme


101

Bir süredir bir sınıf için Java projesi üzerinde çalışıyorum. Bağlantılı bir listenin uygulamasıdır (burada adı verilir AddressList, adı verilen basit düğümleri içerir)ListNode ). İşin püf noktası, her şeyin yinelemeli algoritmalarla yapılması gerektiğidir. Tek bir yöntemle her şeyi iyi yapabildim:public AddressList reverse()

ListNode:

public class ListNode{
  public String data;
  public ListNode next;
}

Şu anda benim reverseişlevim özyinelemeye izin vermek için bir argüman alan bir yardımcı işlevi çağırıyor.

public AddressList reverse(){
  return new AddressList(this.reverse(this.head));
}

Benim yardımcı fonksiyonumun imzası var private ListNode reverse(ListNode current).

Şu anda, bir yığın kullanarak yinelemeli olarak çalışmasını sağlıyorum, ancak bu şartnamenin gerektirdiği şey değil. C'de yinelemeli olarak tersine çeviren ve elle Java koduna dönüştüren bir algoritma buldum ve işe yaradı, ancak bunu anlamadım.

Düzenleme: Boşver, bu arada anladım.

private AddressList reverse(ListNode current, AddressList reversedList){
  if(current == null) 
      return reversedList;
  reversedList.addToFront(current.getData());
  return this.reverse(current.getNext(), reversedList);
}

Ben buradayken, bu rotayla ilgili herhangi bir sorun gören var mı?


2
Hayır, çözümünüzde bir sorun yok. Aksine, orijinal listeyi olduğu gibi bırakması açısından tercih edilen "Little Lisper" çözümünden bile "daha iyidir". Bu, özellikle değişmez değerlerin şiddetle tercih edildiği çok çekirdekli bir ortamda değerli olacaktır.
Ingo

Yanıtlar:


318

Bir yanıtta onu açıklayan bir kod var, ancak küçük sorular sorup yanıtlayarak aşağıdan yukarıya başlamayı daha kolay bulabilirsiniz (The Little Lisper'daki yaklaşım budur):

  1. Null değerinin tersi nedir (boş liste)? boş.
  2. Tek element listesinin tersi nedir? eleman.
  3. Bir n eleman listesinin tersi nedir? listenin geri kalanının tersi ve ardından ilk öğe.

public ListNode Reverse(ListNode list)
{
    if (list == null) return null; // first question

    if (list.next == null) return list; // second question

    // third question - in Lisp this is easy, but we don't have cons
    // so we grab the second element (which will be the last after we reverse it)

    ListNode secondElem = list.next;

    // bug fix - need to unlink list from the rest or you will get a cycle
    list.next = null;

    // then we reverse everything from the second element on
    ListNode reverseRest = Reverse(secondElem);

    // then we join the two lists
    secondElem.next = list;

    return reverseRest;
}

30
Vay canına, tüm bu "Üç soru" olayını seviyorum
sdellysse

4
Teşekkürler. Küçük soru meselesinin Lisp öğrenmenin temeli olması gerekiyor. Bu aynı zamanda, indüksiyonu yenilerden gizlemenin bir yolu, ki bu esasen bu modeldir. Bu tür bir sorunu gerçekten çözmek istiyorsanız Little Lisper'ı okumanızı tavsiye ederim.
kaide

44
istisnai durumlar için istisnalar. Neden bir if ile test edilebilen bilinen bir koşul için bir catch kullanalım?
Luke Schafer

4
List.next hala secondElem olduğu için: secondElem değişkenini yaratmanıza gerek olmadığına inanıyorum. "ListNode reverseRest = Reverse (secondElem);" den sonra, önce "list.next.next = list" ve sonra "list.next = null" yapabilirsiniz. Ve bu kadar.
ChuanRocks

3
List.next = null nedenini açıklayabilir misiniz? Döngüyü anlamaya çalışıyordum ama anlamadım.
Rohit

29

Bu soruyu bir röportajda sormuştum ve biraz gergin olduğum için onunla uğraştığım için sinirlenmiştim.

Bu, ters (head, NULL) ile çağrılan tekil bağlantılı bir listeyi tersine çevirmelidir; öyleyse bu sizin listeniz olsaydı:

1-> 2-> 3-> 4-> 5-> boş
olur:
5-> 4-> 3-> 2-> 1-> boş

    //Takes as parameters a node in a linked list, and p, the previous node in that list
    //returns the head of the new list
    Node reverse(Node n,Node p){   
        if(n==null) return null;
        if(n.next==null){ //if this is the end of the list, then this is the new head
            n.next=p;
            return n;
        }
        Node r=reverse(n.next,n);  //call reverse for the next node, 
                                      //using yourself as the previous node
        n.next=p;                     //Set your next node to be the previous node 
        return r;                     //Return the head of the new list
    }
    

düzenleme: bunun benim için hala biraz zor olduğunu gösteren 6 düzenleme yaptım lol


2
Java belirtilirse, dürüst olmak gerekirse, bir röportajdaki "yinelemeli olmalıdır" gerekliliği beni biraz şaşırtabilir. Aksi takdirde p = null; while (n.next! = null) {n2 = n.next; n.next = p; p = n; n = n2;} n.sonraki = p; dönüş n ;. O (N) yığını kuşlar içindir.
Steve Jessop

Oh evet, kafada da boş bir kontrol, bu Java.
Steve Jessop

23

Yarı yolda kaldım (boş olana ve kaide tarafından önerildiği gibi bir düğüme kadar), ancak yinelemeli arama yaptıktan sonra izimi kaybettim. Ancak, yazıyı kaide ile okuduktan sonra, şunu buldum:

Node reverse(Node head) {
  // if head is null or only one node, it's reverse of itself.
  if ( (head==null) || (head.next == null) ) return head;

  // reverse the sub-list leaving the head node.
  Node reverse = reverse(head.next);

  // head.next still points to the last element of reversed sub-list.
  // so move the head to end.
  head.next.next = head;

  // point last node to nil, (get rid of cycles)
  head.next = null;
  return reverse;
}

çok güzel. aynen eksilerini yapmak gibi :)
Karthikeyan D

9

İşte yine başka bir özyinelemeli çözüm. Özyinelemeli işlev içinde diğerlerinden daha az koda sahiptir, bu nedenle biraz daha hızlı olabilir. Bu C # ama Java'nın çok benzer olacağına inanıyorum.

class Node<T>
{
    Node<T> next;
    public T data;
}

class LinkedList<T>
{
    Node<T> head = null;

    public void Reverse()
    {
        if (head != null)
            head = RecursiveReverse(null, head);
    }

    private Node<T> RecursiveReverse(Node<T> prev, Node<T> curr)
    {
        Node<T> next = curr.next;
        curr.next = prev;
        return (next == null) ? curr : RecursiveReverse(curr, next);
    }
}

8

Algo'nun aşağıdaki model üzerinde çalışması gerekecek,

  • kafayı takip et
  • Bağlantı listesinin sonuna kadar yineleyin
  • Ters bağlantı

Yapısı:

Head    
|    
1-->2-->3-->4-->N-->null

null-->1-->2-->3-->4-->N<--null

null-->1-->2-->3-->4<--N<--null

null-->1-->2-->3<--4<--N<--null

null-->1-->2<--3<--4<--N<--null

null-->1<--2<--3<--4<--N<--null

null<--1<--2<--3<--4<--N
                       |
                       Head

Kod:

public ListNode reverse(ListNode toBeNextNode, ListNode currentNode)
{               
        ListNode currentHead = currentNode; // keep track of the head

        if ((currentNode==null ||currentNode.next==null )&& toBeNextNode ==null)return currentHead; // ignore for size 0 & 1

        if (currentNode.next!=null)currentHead = reverse(currentNode, currentNode.next); // travarse till end recursively

        currentNode.next = toBeNextNode; // reverse link

        return currentHead;
}

Çıktı:

head-->12345

head-->54321

7

Bence bu daha temiz bir çözüm, LISP'ye benziyor

// Example:
// reverse0(1->2->3, null) => 
//      reverse0(2->3, 1) => 
//          reverse0(3, 2->1) => reverse0(null, 3->2->1)
// once the first argument is null, return the second arg
// which is nothing but the reveresed list.

Link reverse0(Link f, Link n) {
    if (f != null) {
        Link t = new Link(f.data1, f.data2); 
        t.nextLink = n;                      
        f = f.nextLink;             // assuming first had n elements before, 
                                    // now it has (n-1) elements
        reverse0(f, t);
    }
    return n;
}

7

Bunun eski bir gönderi olduğunu biliyorum, ancak cevapların çoğu tekrarlı değil, yani yinelemeli aramadan döndükten sonra bazı işlemleri yapıyorlar ve bu nedenle en verimli olanı değiller.

İşte bir kuyruk özyinelemeli versiyonu:

public Node reverse(Node previous, Node current) {
    if(previous == null)
        return null;
    if(previous.equals(head))
        previous.setNext(null);
    if(current == null) {    // end of list
        head = previous;
        return head;
    } else {
                    Node temp = current.getNext();
        current.setNext(previous);
        reverse(current, temp);
    }
    return null;    //should never reach here.
} 

İle ara:

Node newHead = reverse(head, head.getNext());

9
yönteminizde "head" adlı bir değişkene başvurursunuz, ancak bu herhangi bir yerde bildirilmez.
maraton

Muhtemelen Node head özniteliğini içeren List sınıfının bir yöntemidir
ChrisMcJava

4
void reverse (node1, node2) {
eğer (node1.next! = null)
      ters (düğüm1.sonraki, düğüm1);
   node1.next = node2;
}
bu yöntemi ters olarak çağırın (başlangıç, boş);

4
public Node reverseListRecursive(Node curr)
{
    if(curr == null){//Base case
        return head;
    }
    else{
        (reverseListRecursive(curr.next)).next = (curr);
    }
    return curr;
}

3
public void reverse() {
    head = reverseNodes(null, head);
}

private Node reverseNodes(Node prevNode, Node currentNode) {
    if (currentNode == null)
        return prevNode;
    Node nextNode = currentNode.next;
    currentNode.next = prevNode;
    return reverseNodes(currentNode, nextNode);
}

Bence bu en iyi çözüm ... basit, kuyruk özyinelemeli optimize edilebilir ve sadece bir boş kontrol.
sdanzig

2
public static ListNode recRev(ListNode curr){

    if(curr.next == null){
        return curr;
    }
    ListNode head = recRev(curr.next);
    curr.next.next = curr;
    curr.next = null;

    // propogate the head value
    return head;

}

Bu en iyi çözümdür, ancak hiçbir açıklama yapılmadığı için en iyi cevap değildir :). İlk başta benzer bir çözüm buldum ama baş referansı kaybettim. Bu çözüm bunu çözüyor.
OpenUserX03

2

Özyinelemeli algo ile ters çevir.

public ListNode reverse(ListNode head) {
    if (head == null || head.next == null) return head;    
    ListNode rHead = reverse(head.next);
    rHead.next = head;
    head = null;
    return rHead;
}

Yinelemeli

public ListNode reverse(ListNode head) {
    if (head == null || head.next == null) return head;    
    ListNode prev = null;
    ListNode cur = head
    ListNode next = head.next;
    while (next != null) {
        cur.next = prev;
        prev = cur;
        cur = next;
        next = next.next;
    }
    return cur;
}

Ne yazık ki yinelemeli tersiniz Yanlış !!
Sree Aurovindh

@SreeAurovindh - Neden?
rayryeng

2

Bu çözüm, hiçbir argümana gerek olmadığını gösterir.

/**
 * Reverse the list
 * @return reference to the new list head
 */
public LinkNode reverse() {
    if (next == null) {
        return this; // Return the old tail of the list as the new head
    }
    LinkNode oldTail = next.reverse(); // Recurse to find the old tail
    next.next = this; // The old next node now points back to this node
    next = null; // Make sure old head has no next
    return oldTail; // Return the old tail all the way back to the top
}

İşte bunun işe yaradığını göstermek için destekleyici kod:

public class LinkNode {
    private char name;
    private LinkNode next;

    /**
     * Return a linked list of nodes, whose names are characters from the given string
     * @param str node names
     */
    public LinkNode(String str) {
        if ((str == null) || (str.length() == 0)) {
            throw new IllegalArgumentException("LinkNode constructor arg: " + str);
        }
        name = str.charAt(0);
        if (str.length() > 1) {
            next = new LinkNode(str.substring(1));
        }
    }

    public String toString() {
        return name + ((next == null) ? "" : next.toString());
    }

    public static void main(String[] args) {
        LinkNode head = new LinkNode("abc");
        System.out.println(head);
        System.out.println(head.reverse());
    }
}

2

İşte basit bir yinelemeli yaklaşım:

public static Node reverse(Node root) {
    if (root == null || root.next == null) {
        return root;
    }

    Node curr, prev, next;
    curr = root; prev = next = null;
    while (curr != null) {
        next = curr.next;
        curr.next = prev;

        prev = curr;
        curr = next;
    }
    return prev;
}

Ve işte yinelemeli bir yaklaşım:

public static Node reverseR(Node node) {
    if (node == null || node.next == null) {
        return node;
    }

    Node next = node.next;
    node.next = null;

    Node remaining = reverseR(next);
    next.next = node;
    return remaining;
}

1

Java her zaman değere göre geçirildiğinden, Java'da bağlantılı bir listeyi özyinelemeli olarak tersine çevirmek için özyinelemenin sonunda "yeni baş" (ters çevirmeden sonra baş düğüm) döndürdüğünüzden emin olun.

static ListNode reverseR(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    ListNode first = head;
    ListNode rest = head.next;

    // reverse the rest of the list recursively
    head = reverseR(rest);

    // fix the first node after recursion
    first.next.next = first;
    first.next = null;

    return head;
}

1

PointZeroTwo'nun zarif bir cevabı var ve Java'da aynı ...

public void reverseList(){
    if(head!=null){
        head = reverseListNodes(null , head);
    }
}

private Node reverseListNodes(Node parent , Node child ){
    Node next = child.next;
    child.next = parent;
    return (next==null)?child:reverseListNodes(child, next);
}

Bu mükemmel çünkü bu liste yönteminin listeyi her zaman argüman olarak almasını değil, kendi çocuklarıyla tersine çevirmesini istiyorsun, teşekkür ederim
Manu

0
public class Singlelinkedlist {
  public static void main(String[] args) {
    Elem list  = new Elem();
    Reverse(list); //list is populate some  where or some how
  }

  //this  is the part you should be concerned with the function/Method has only 3 lines

  public static void Reverse(Elem e){
    if (e!=null)
      if(e.next !=null )
        Reverse(e.next);
    //System.out.println(e.data);
  }
}

class Elem {
  public Elem next;    // Link to next element in the list.
  public String data;  // Reference to the data.
}

0
public Node reverseRec(Node prev, Node curr) {
    if (curr == null) return null;  

    if (curr.next == null) {
        curr.next = prev;
        return curr;

    } else {
        Node temp = curr.next; 
        curr.next = prev;
        return reverseRec(curr, temp);
    }               
}

kullanarak çağrı: head = reverseRec (null, head);


0

Diğerlerinin yaptığı şey, diğer gönderide bir içerik oyunuydu, yaptığım şey bağlantılı liste oyunuydu, LinkedList'in üyesini tersine çevirmek, üyelerin Değerini tersine çevirmek değil.

Public LinkedList reverse(LinkedList List)
{
       if(List == null)
               return null;
       if(List.next() == null)
              return List;
       LinkedList temp = this.reverse( List.next() );
       return temp.setNext( List );
}

sry de unuttum kuyruğun bir sonraki değerini sıfır değerle ayarlamak için yardımcı bir yönteme ihtiyacınız var
Nima Ghaedsharafi

0
package com.mypackage;
class list{

    node first;    
    node last;

    list(){
    first=null;
    last=null;
}

/*returns true if first is null*/
public boolean isEmpty(){
    return first==null;
}
/*Method for insertion*/

public void insert(int value){

    if(isEmpty()){
        first=last=new node(value);
        last.next=null;
    }
    else{
        node temp=new node(value);
        last.next=temp;
        last=temp;
        last.next=null;
    }

}
/*simple traversal from beginning*/
public void traverse(){
    node t=first;
    while(!isEmpty() && t!=null){
        t.printval();
        t= t.next;
    }
}
/*static method for creating a reversed linked list*/
public static void reverse(node n,list l1){

    if(n.next!=null)
        reverse(n.next,l1);/*will traverse to the very end*/
    l1.insert(n.value);/*every stack frame will do insertion now*/

}
/*private inner class node*/
private class node{
    int value;
    node next;
    node(int value){
        this.value=value;
    }
    void printval(){
        System.out.print(value+" ");
    }
}

 }

0

Çözüm şudur:

package basic;

import custom.ds.nodes.Node;

public class RevLinkedList {

private static Node<Integer> first = null;

public static void main(String[] args) {
    Node<Integer> f = new Node<Integer>();
    Node<Integer> s = new Node<Integer>();
    Node<Integer> t = new Node<Integer>();
    Node<Integer> fo = new Node<Integer>();
    f.setNext(s);
    s.setNext(t);
    t.setNext(fo);
    fo.setNext(null);

    f.setItem(1);
    s.setItem(2);
    t.setItem(3);
    fo.setItem(4);
    Node<Integer> curr = f;
    display(curr);
    revLL(null, f);
    display(first);
}

public static void display(Node<Integer> curr) {
    while (curr.getNext() != null) {
        System.out.println(curr.getItem());
        System.out.println(curr.getNext());
        curr = curr.getNext();
    }
}

public static void revLL(Node<Integer> pn, Node<Integer> cn) {
    while (cn.getNext() != null) {
        revLL(cn, cn.getNext());
        break;
    }
    if (cn.getNext() == null) {
        first = cn;
    }
    cn.setNext(pn);
}

}


0
static void reverseList(){

if(head!=null||head.next!=null){
ListNode tail=head;//head points to tail


ListNode Second=head.next;
ListNode Third=Second.next;
tail.next=null;//tail previous head is poiniting null
Second.next=tail;
ListNode current=Third;
ListNode prev=Second;
if(Third.next!=null){



    while(current!=null){
    ListNode    next=current.next;
        current.next=prev;
        prev=current;
        current=next;
    }
    }
head=prev;//new head
}
}
class ListNode{
    public int data;
    public ListNode next;
    public int getData() {
        return data;
    }

    public ListNode(int data) {
        super();
        this.data = data;
        this.next=null;
    }

    public ListNode(int data, ListNode next) {
        super();
        this.data = data;
        this.next = next;
    }

    public void setData(int data) {
        this.data = data;
    }
    public ListNode getNext() {
        return next;
    }
    public void setNext(ListNode next) {
        this.next = next;
    }





}

0
private Node ReverseList(Node current, Node previous)
    {
        if (current == null) return null;
        Node originalNext = current.next;
        current.next = previous;
        if (originalNext == null) return current;
        return ReverseList(originalNext, current);
    }

ReverseList ile başla (head, null)
pat

0
//this function reverses the linked list
public Node reverseList(Node p) {
    if(head == null){
        return null;
    }
    //make the last node as head
    if(p.next == null){
        head.next = null;
        head = p;
        return p;
    }
    //traverse to the last node, then reverse the pointers by assigning the 2nd last node to last node and so on..
    return reverseList(p.next).next = p;
}

0
//Recursive solution
class SLL
{
   int data;
   SLL next;
}

SLL reverse(SLL head)
{
  //base case - 0 or 1 elements
  if(head == null || head.next == null) return head;

  SLL temp = reverse(head.next);
  head.next.next = head;
  head.next = null;
  return temp;
}

0

Bir makaleden esinlenildiÖzyinelemeli veri yapılarının değişmez uygulamalarını tartışan Swift kullanarak alternatif bir çözümü bir araya getirdim.

Aşağıdaki konuları vurgulayarak önde gelen yanıt belgeleri çözümü:

  1. Nil'in tersi nedir (boş liste)?
    • Burada önemli değil, çünkü Swift'de sıfır korumamız var.
  2. Tek element listesinin tersi nedir?
    • Elemanın kendisi
  3. Bir n eleman listesinin tersi nedir?
    • İkinci elemanın tersi, ardından birinci eleman.

Bunları aşağıdaki çözümde uygun olan yerlerde çağırdım.

/**
 Node is a class that stores an arbitrary value of generic type T 
 and a pointer to another Node of the same time.  This is a recursive 
 data structure representative of a member of a unidirectional linked
 list.
 */
public class Node<T> {
    public let value: T
    public let next: Node<T>?

    public init(value: T, next: Node<T>?) {
        self.value = value
        self.next = next
    }

    public func reversedList() -> Node<T> {
        if let next = self.next {
            // 3. The reverse of the second element on followed by the first element.
            return next.reversedList() + value
        } else {
            // 2. Reverse of a one element list is itself
            return self
        }
    }
}

/**
 @return Returns a newly created Node consisting of the lhs list appended with rhs value.
 */
public func +<T>(lhs: Node<T>, rhs: T) -> Node<T> {
    let tail: Node<T>?
    if let next = lhs.next {
        // The new tail is created recursively, as long as there is a next node.
        tail = next + rhs
    } else {
        // If there is not a next node, create a new tail node to append
        tail = Node<T>(value: rhs, next: nil)
    }
    // Return a newly created Node consisting of the lhs list appended with rhs value.
    return Node<T>(value: lhs.value, next: tail)
}

0

Özyineleme kullanarak bağlantılı listeyi ters çevirme. Fikir, bağlantıları ters çevirerek bağlantıları ayarlamaktır.

  public ListNode reverseR(ListNode p) {

       //Base condition, Once you reach the last node,return p                                           
        if (p == null || p.next == null) { 
            return p;
        }
       //Go on making the recursive call till reach the last node,now head points to the last node

        ListNode head  = reverseR(p.next);  //Head points to the last node

       //Here, p points to the last but one node(previous node),  q points to the last   node. Then next next step is to adjust the links
        ListNode q = p.next; 

       //Last node link points to the P (last but one node)
        q.next = p; 
       //Set the last but node (previous node) next to null
        p.next = null; 
        return head; //Head points to the last node
    }

1
Sağladığınız çözüm hakkında biraz daha açıklama ekleyerek yanıtınızı biraz daha detaylandırır mısınız?
abarisone

1
Yorum ekledim Çok teşekkürler
gurubelli

0
public void reverseLinkedList(Node node){
    if(node==null){
        return;
    }

    reverseLinkedList(node.next);
    Node temp = node.next;
    node.next=node.prev;
    node.prev=temp;
    return;
}

-1
public void reverse(){
    if(isEmpty()){
    return;
     }
     Node<T> revHead = new Node<T>();
     this.reverse(head.next, revHead);
     this.head = revHead;
}

private Node<T> reverse(Node<T> node, Node<T> revHead){
    if(node.next == null){
       revHead.next = node;
       return node;
     }
     Node<T> reverse = this.reverse(node.next, revHead);
     reverse.next = node;
     node.next = null;
     return node;
}

-1

Biri Scala uygulamasını arıyorsa işte bir referans:

scala> import scala.collection.mutable.LinkedList
import scala.collection.mutable.LinkedList

scala> def reverseLinkedList[A](ll: LinkedList[A]): LinkedList[A] =
         ll.foldLeft(LinkedList.empty[A])((accumulator, nextElement) => nextElement +: accumulator)
reverseLinkedList: [A](ll: scala.collection.mutable.LinkedList[A])scala.collection.mutable.LinkedList[A]

scala> reverseLinkedList(LinkedList("a", "b", "c"))
res0: scala.collection.mutable.LinkedList[java.lang.String] = LinkedList(c, b, a)

scala> reverseLinkedList(LinkedList("1", "2", "3"))
res1: scala.collection.mutable.LinkedList[java.lang.String] = LinkedList(3, 2, 1)

Olumsuz oy kullanan kişi bana eylemine bir açıklama yaparsa cevabımı iyileştirmekten çok mutlu olurum. Her neyse, Scala'da hala benim için çalışıyor :)
Venkat Sudheer Reddy Aedama

Olumsuz oy verenin bildiği gibi, bu özyinelemeli (aslında bir kuyruk özyinelemeli) çözümdür.
Venkat Sudheer Reddy Aedama

Scala, ikisi de JVM üzerinde çalışsalar bile Java değildir.
Bill Lynch

@sharth Wow, bunu bilmek güzel. Cevabımın ilk satırını okudunuz mu?
Venkat Sudheer Reddy Aedama

@VenkatSudheerReddyAedama Orijinal soru Java'da bir uygulama istediği için olumsuz oy verdiniz. Scala JVM'de çalışsa da, bu oldukça zarif olmasına rağmen soruyu cevaplamada yardımcı olmuyor. FWIW, sana olumsuz oy vermedim.
rayryeng
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.