Linkitetty lista on tietorakenne, jossa listan jäsenet tietävät seuraavan listan jäsenen (yhteen suuntaan linkitetty lista) tai vaihtoehtoisesti edellisen ja seuraavan jäsenen listassa (kahteen suuntaan linkitetty lista).
//============================================================================ // Name : LinkitettyLista.cpp // Author : jes // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #define DATATIEDOSTO "tietoll.dat" using namespace std; void valikko(); struct Kaverit //Tietueen kuvaus { char Nimi[50]; char Osoite[50]; char PuhNo[50]; Kaverit *pSeuraava; //osoitin seuraavaan tietueeseen }; int KokoTiedostonKirjoitusLevylle(Kaverit *pEnsimmainen); void TiedostonLukuLevylta(Kaverit **ppListanAlku, Kaverit **ppListanLoppu); void TalletaListaan(Kaverit *pUusi, //uusi tieto listaan Kaverit **ppListanAlku, //osoitin listan alkuun Kaverit **ppListanLoppu);//osoitin listan loppuun void TuhoaTietue(Kaverit *pEdellinen, Kaverit *pTuhottava, Kaverit **ppAlku, Kaverit **ppLoppu); Kaverit *EtsiNimella(Kaverit *pAlku,Kaverit **ppEdellinen, char *pEtsittavaNimi); Kaverit *HaeNimella(Kaverit *pAlku,Kaverit **pEdellinen); void NaytaTietueetJarjestyksessa(Kaverit *pAlku); void TietueidenTaytto(Kaverit *pUusi,Kaverit **ppListanAlku, Kaverit **ppListanLoppu); int Debug=1;// int main() { int apu; int valitsin = '1'; Kaverit *pUusi=NULL,*pTietue=NULL; Kaverit *pEdellinen=NULL, *pAlku=NULL,*pLoppu=NULL; TiedostonLukuLevylta(&pAlku,&pLoppu); for (;;) {valikko(); cin >>valitsin; switch (valitsin) { case 0: /*free(pTutut);*/ exit(1); break; case 1: pUusi=new Kaverit; TietueidenTaytto(pUusi,&pAlku,&pLoppu); KokoTiedostonKirjoitusLevylle(pAlku); break; case 2: pTietue=pAlku; pTietue=HaeNimella(pTietue,&pEdellinen); //printf("\n %s %s %s ", // pTietue->Nimi,pTietue->Osoite,pTietue->PuhNo); //cin>>apu; break; case 3: NaytaTietueetJarjestyksessa(pAlku); break; case 4: pTietue=pAlku; pTietue=HaeNimella(pTietue,&pEdellinen); if(pTietue!=NULL) { if(Debug==1) cout<<"\nAion tuhota tietueen"; TuhoaTietue( pEdellinen, pTietue, &pAlku, &pLoppu); KokoTiedostonKirjoitusLevylle(pAlku); } else { cout<<"EI TUHOTTAVAA"; //cin>>apu; } break; } } } void TietueidenTaytto(Kaverit *pUusi, Kaverit **ppListanAlku,Kaverit **ppListanLoppu) { //system("cls"); cout<<"\nAnna kaverin nimi max. 50 kirjainta "; cin>>pUusi->Nimi; cout<<"\nAnna kaverin osoite max. 50 kirjainta"; cin>>pUusi->Osoite; cout<<"\nAnna kaverin puh.no max. 50 kirjainta"; cin>>pUusi->PuhNo; TalletaListaan( pUusi, ppListanAlku, ppListanLoppu); } void valikko(void) { //clrscr(); cout<<"\n\n\n"; cout<<"\n 0........Lopetus"; cout<<"\n 1........Tietojen taytto tietokantaan"; cout<<"\n 2........Haku nimell ja tietojen nytt"; cout<<"\n 3........Kaikkien tietojen nytt"; cout<<"\n 4........Halutun tietueen tuhoaminen"; } /****************************************************************** Funktion nimi HaeNimella Paluuarvo : Kaverit tyyppi oleva osoitin Parametrit: 1. Kaverit tyyppi oleva osoitin, joka osoittaa linkitetyn listan ensimmiseen elementtiin 2. Kaverit tyyppinen osoitin, osoittimeen Kaverit. Parametri tytyy vlitt nin, jotta kutsuva ohjelma "nkisi" tietueosoittimen muutoksen. *******************************************************************/ Kaverit *HaeNimella(Kaverit *pAlku,Kaverit **ppEdellinen ) { char pEtsittavaNimi[50]; Kaverit *pEtsittava; cout<<"\nAnna etsittvn nimi"; cin>>pEtsittavaNimi; pEtsittava = EtsiNimella(pAlku, ppEdellinen,pEtsittavaNimi); if(pEtsittava!=NULL) cout << pEtsittava->Nimi <<" "<< pEtsittava->Osoite<<" "<<pEtsittava->PuhNo; return pEtsittava; } //tietueet sisltvn tiedoston luku void TiedostonLukuLevylta(Kaverit **ppListanAlku, Kaverit **ppListanLoppu) { FILE *Tiedosto; int iLukum=0; //esitellaan paikallinen tietuemuuttuja Kaverit Henkilo,*pUusi; Tiedosto=fopen(DATATIEDOSTO,"rb"); if(Tiedosto==NULL) { cout<<"tiedostoa ei ole"; return ; } do {//luetaan levylta yksi tietue muuttujaan henkilo iLukum=fread(&Henkilo,sizeof(Kaverit),1,Tiedosto); if(iLukum==1) { pUusi = new Kaverit; *pUusi=Henkilo; TalletaListaan( pUusi, ppListanAlku, ppListanLoppu); } }while (iLukum==1); fclose(Tiedosto); return ; } /******************************************************************* kaikkien tietueiden yhtaikainen kirjoitus levylle funktio ottaa parametreikseen ensimmisen tietueen osoitteen, sek talletettavien tietueiden mrn *******************************************************************/ int KokoTiedostonKirjoitusLevylle(Kaverit *pEnsimmainen) { int apu; FILE *Tiedosto; int iLukum=0; Tiedosto=fopen(DATATIEDOSTO,"wb"); if(Tiedosto==NULL) { printf("\nTiedosto ei aukea kirjoitettavaksi"); //cin>>apu; return iLukum; } iLukum=fwrite(pEnsimmainen,sizeof(struct Kaverit),1,Tiedosto); pEnsimmainen=pEnsimmainen->pSeuraava; fclose(Tiedosto); Tiedosto=fopen(DATATIEDOSTO,"ab"); if(Tiedosto==NULL) { cout<<"Tiedosto ei aukea kirjoitettavaksi"; //cin>>apu; return iLukum; } while(pEnsimmainen) { iLukum=fwrite(pEnsimmainen,sizeof(struct Kaverit),1,Tiedosto); pEnsimmainen=pEnsimmainen->pSeuraava; } if(iLukum!=1) { cout<<"Uuden tietueen kirjoitus ei onnistu"; //cin>>apu; exit(1); } fclose(Tiedosto); return iLukum; } /******************************************************************* Funktio tallettaa uuden tietueen listassa oikeaan paikkaan *******************************************************************/ void TalletaListaan(Kaverit *pUusi, //uusi tieto listaan Kaverit **ppListanAlku, //osoitin listan alkuun Kaverit **ppListanLoppu)//osoitin listan loppuun { int apu; Kaverit *pVanha, *pTemp; pTemp = *ppListanAlku; if(!*ppListanLoppu)//viimeist ei ole { pUusi->pSeuraava = NULL; *ppListanLoppu = pUusi; *ppListanAlku = pUusi; if(Debug==1) { cout<<"\nEnsimminen"; cout<<"\nAlku" <<(*ppListanAlku)->Nimi; cout<<"\n Uusi "<<pUusi->Nimi; cout<<"\nLoppu "<<(*ppListanLoppu)->Nimi; //cin>>apu; } return; } pVanha= NULL; while(pTemp) { if(strcmp(pTemp->Nimi, pUusi->Nimi)<0) { pVanha = pTemp; pTemp = pTemp->pSeuraava; } else { if (pVanha) { pVanha->pSeuraava = pUusi; pUusi->pSeuraava = pTemp; if(Debug==1) { cout<<"Valiin"; cout<<"\nAlku "<<(*ppListanAlku)->Nimi; cout<<" Uusi "<<pUusi->Nimi; cout<<" Loppu "<<(*ppListanLoppu)->Nimi; //cin>>apu; } return; } pUusi->pSeuraava =pTemp;//uusi ensimminen elementti *ppListanAlku=pUusi; if(Debug==1) { cout<<"\nAlkuun"; cout<<"\nAlku "<<(*ppListanAlku)->Nimi; cout<<" Uusi "<<pUusi->Nimi; cout<<" Loppu "<<(*ppListanLoppu)->Nimi; //cin>>apu; } return; } } (*ppListanLoppu)->pSeuraava=pUusi;//laitetaan listan loppuun pUusi->pSeuraava=NULL;//"maadoitetaan loppu" *ppListanLoppu= pUusi; if(Debug==1) { cout<<"\nLoppuun"; cout<<"\nAlku ",(*ppListanAlku)->Nimi; cout<<" Uusi "<<pUusi->Nimi; cout<<" Loppu "<<(*ppListanLoppu)->Nimi; //cin>>apu; } } /******************************************************************* *******************************************************************/ void NaytaTietueetJarjestyksessa(Kaverit *pAlku) { int apu; // clrscr(); cout<<"\nNimi Osoite Puhelin "; while(pAlku) { cout<< "\n"<<pAlku->Nimi<<" "<<pAlku->Osoite<<" "<<pAlku->PuhNo; //siirretn osoitin seuraavaan tietueeseen pAlku=pAlku->pSeuraava; } //cout<<"\nPAINA ENTER"; //cin>>apu; } /************************************************************ Funktio etsii listasta nime vastaavan tietueen Huom! Funktio EI MUUTA pAlku osoittimen paikkaa Funktio palauttaa etsityn tietueen osoitteen *************************************************************/ Kaverit *EtsiNimella(Kaverit *pAlku, Kaverit **ppEdellinen ,char *pEtsittavaNimi) { while(pAlku) { if (!strcmp(pEtsittavaNimi,pAlku->Nimi)) return pAlku; //Siirretaan nykyinen edelliseksi *ppEdellinen=pAlku; // pAlku=pAlku->pSeuraava; } if(Debug==1){cout<<"Ei loydy";} return NULL; //ei lytynyt } /******************************************************************* *******************************************************************/ void TuhoaTietue(Kaverit *pEdellinen, Kaverit *pTuhottava, Kaverit **ppAlku, Kaverit **ppLoppu) { if(pEdellinen) pEdellinen->pSeuraava= pTuhottava->pSeuraava; else *ppAlku=pTuhottava->pSeuraava; if(pTuhottava==*ppLoppu && pEdellinen) *ppLoppu =pEdellinen; delete pTuhottava; }