// Rifat ��lkesen' in 'iste c programlama' adli kitabindaki 'yapisal veri tipleri'
// konusu icin yazilmis dinamik bagli dizge ornegi. Ozellikle arama ve dugum ekleme
// islevlerine dikkat edilmeli; sanat orada yatiyor. Kitapta verilen ornek cok
// kucuk bazi degisikliklerle telefon defteri uygulamasina donusturulmustur. Dizge
// bir agac biciminde kurulmustur (tree). Bunun icin ilgili bolum calisilmalidir.
// ozcoban@istanbul.edu.tr       - Ozgur.Cobanoglu@cern.ch
// ozgur@nucleus.istanbul.edu.tr - ozgur_cobanoglu@hotmail.com

#include<iostream.h>

typedef struct kayit{
    char ad[21];
    char soyad[31];
    char tel[31];
    struct kayit *sol, *sag;
} KAYIT;

KAYIT *kok = NULL;

// menudenSecimYap()
//____________________________________________________________________
int menudenSecimYap() {
    char *menu[7]={"[1]...EKLE",  "[2]...ARA", "[3]...SIRALA","[4]...SiL",
                   "[5]...KAYDET","[6]...OKU","[7]...KAPAT"};
    int i,c;
    printf("\n\t  --- TELEFON DEFTERi ---\n\t  -----------------------\n");
    for (i=0 ; i<7 ; i++) printf("\t\t%s\n",menu[i]);
    do {
        printf("SE�iMiNiZ :\n");
        scanf("%d", &c);
    } while(c<1 || c>7);
    return c;
}

// dugumEkle()
//____________________________________________________________________
void dugumEkle(KAYIT *agac, KAYIT *ekle) {
    if (!agac) {
        kok=ekle;
        //printf("\nKayit eklendi...\n");
        return;
    } else {
        if (strcmp(ekle->ad, agac->ad)<0 ||
        (strcmp(ekle->ad, agac->ad)==0 && strcmp(ekle->soyad, agac->soyad)<0)) {
            if (!agac->sol) {
                agac->sol=ekle;
                //printf("\nKayit sola eklendi...\n");
                return;
            } else {
                dugumEkle(agac->sol, ekle);
                return;
            }
        } else {
            if (!agac->sag) {
                agac->sag=ekle;
                //printf("\nKayit saga eklendi...\n");
                return;
            } else {
                dugumEkle(agac->sag, ekle);
                return;
            }
        }
    }
}

// kayit()
//____________________________________________________________________
void kayit() {
    KAYIT *al;
    al=(KAYIT*)malloc(sizeof(KAYIT));
    if (!al) {
        printf("Yer yok ekleyemem !..\n");
        return;
    }
    printf("AD...........: ");
    scanf("%20s", al->ad);
    printf("SOYAD........: ");
    scanf("%30s", al->soyad);
    printf("TEL NO.......: ");
    scanf("%30s", al->tel);
    al->sol = NULL;
    al->sag = NULL;
    dugumEkle(kok, al);
}

// goster()
//____________________________________________________________________
void goster(KAYIT *kayit) {
    printf("\nARAMA SONUCU\n----------------\nAD......: %s\n", kayit->ad);
    printf("SOYAD...: %s\n", kayit->soyad);
    printf("TEL NO..: %s\n----------------\n", kayit->tel);
    char kr;
    kr=getchar();
}

// taraAgac()
//____________________________________________________________________
void taraAgac(KAYIT *agac, char *ad) {
    if (!agac) return;
    taraAgac(agac->sol, ad);
    if (!strcmp(agac->ad, ad)) {
        goster(agac);
    }
    taraAgac(agac->sag, ad);
}

// arama()
//____________________________________________________________________
void arama() {
    char ad[20];
    printf("Aranan ismi girin :");
    scanf("%20s",ad);
    taraAgac(kok, ad);
}

// agacListele()
//____________________________________________________________________
void agacListele(KAYIT *agac) {
    if (!agac) return;
    agacListele(agac->sol);
    goster(agac);
    agacListele(agac->sag);
}

// dugumSil()
//____________________________________________________________________
KAYIT *dugumSil(KAYIT *agac, char*ad, char*sad) {
    KAYIT *p, *q;
    if (!agac) return NULL;
    if (!strcmp(agac->ad, ad) && !strcmp(agac->soyad, sad)) {
        if (agac->sol == agac->sag) {
            free(agac);
            return NULL;
        } else {
            if (!agac->sol) {
                p=agac->sag;
                free(agac);
                return p;
            } else {
                if (!agac->sag) {
                    p=agac->sol;
                    free(agac);
                    return p;
                } else {
                    p=agac->sag;
                    q=agac->sag;
                    while(p->sol) p=p->sol;
                    p->sol=agac->sol;
                    free(agac);
                    return q;
                }
            }
        }
    }
    int x=strcmp(ad, agac->ad);
    if (x<0 || (x==0 && strcmp(sad, agac->soyad)<0)) {
        agac->sol=dugumSil(agac->sol, ad, sad);
    } else {
        agac->sag=dugumSil(agac->sag, ad, sad);
    }
    return agac;
}

// silme()
//____________________________________________________________________
void silme() {
    KAYIT *kayit;
    char ad[11], soyad[21];
    if (!kok) {
        printf("\nAgac bos, silinecek kayit yok !..\n");
        return;
    }
    printf("Silinecek kayit icin\nAD......: ");
    scanf("%20s", ad);
    printf("SOYAD...: ");
    scanf("%30s", soyad);
    kok=dugumSil(kok, ad, soyad);
}

// dugumKaydet()
//____________________________________________________________________
void dugumKaydet(KAYIT *agac, FILE *di) {
    if (!agac) return;
    fwrite(agac, sizeof(KAYIT)-2*sizeof(agac), 1, di);
    dugumKaydet(agac->sol, di);
    dugumKaydet(agac->sag, di);
}

// sakla()
//____________________________________________________________________
void sakla() {
    FILE *di;
    KAYIT *p;
    if (!kok) {
        printf("\nAgac bos, saklanacak kayit yok !...\n");
        return;
    }
    if (!(di=fopen("telDef.dat","w"))) {
        printf("\nHATA : Dosya acilamadi !..\n");
        return;
    }
    printf("\nDosyaya yaziliyor...\n");
    dugumKaydet(kok, di);
    fclose(di);
}

// yukle()
//____________________________________________________________________
void yukle() {
    FILE *di;
    KAYIT *al;
    unsigned int tane;
    int k, i;
    if ((di=fopen("telDef.dat","r"))==NULL) {
        printf("\nHATA : Dosya acilamadi !...\n");
        return;
    }
    fseek(di, 0, 2);
    tane=ftell(di)/(sizeof(KAYIT)-2*sizeof(al));
    fseek(di, 0, 0);
    if (tane<1) {
        printf("\nDosya bos !..\n");
        return;
    }
    printf("\nDosyadan yukleniyor..\n");
    for (int k=0 ; k<tane ; k++) {
        al=(KAYIT*)malloc(sizeof(KAYIT));
        if (!al) {
            printf("\nHATA : Fiziksel hafiza dolu !..\n");
            break;
        }
        fread(al, sizeof(KAYIT)-2*sizeof(al), 1, di);
        al->sol=NULL;
        al->sag=NULL;
        dugumEkle(kok, al);
    }
    fclose(di);
}

// main()
//____________________________________________________________________
int main() {
    int secim;
    while(1) {
        secim = menudenSecimYap();
        switch(secim) {
            case 1 :
                kayit();
                break;
            case 2 :
                arama();
                break;
            case 3 :
                agacListele(kok);
                break;
            case 4 :
                silme();
                break;
            case 5 :
                sakla();
                break;
            case 6 :
                yukle();
                break;
            case 7 :
                return 0;
        }
    }
return 0;
}