Jumat, 20 Juli 2012

Single Linked List Non Circular



Single Linked List Non Circular
Pengertian: 
Single : artinya field pointer-nya hanya satu buah saja dan satu arah. 
Linked List : artinya node-node tersebut saling terhubung satu sama lain. 
Ilustrasi Linked List 
- Setiap node pada linked list mempunyai field yang berisi pointer ke node
berikutnya, dan juga memiliki field yang berisi data. 
- Pada akhir linked list, node terakhir akan menunjuk ke NULL yang akan 
digunakan sebagai kondisi berhenti pada saat pembacaan isi linked list

Contoh program single linked list non circular tambah list di depan :
# include<stdio.h>
# include<stdlib.h>
# include<conio.h>
# include<iostream.h>
# include<ctype.h>
# include<string.h>

struct simpul
{
            int angka;
            struct simpul*berikut;
} ;

struct simpul *awal=NULL;
int bil;

void tambah_list_didepan(int info);
void isi_list();
void tampil_list();
void hapus_list();

void main ()

{

            clrscr();
            isi_list();
            clrscr();
            tampil_list();
            hapus_list();
            getch();
}
void tambah_list_didepan(int info)
{
            struct simpul *baru;
            baru=(struct simpul *)malloc(sizeof(struct simpul));
            baru->angka=info;

            baru->berikut=awal;


            awal=baru;
}

void isi_list()
{
            char jawab;
            do
            {
            clrscr();
            cout<<"\ninput bilangan :";
            cin>>bil;
            tambah_list_didepan(bil);
            cout<<"\ntambah data Y/T :"  ;
            cin>>jawab;
            }
            while (toupper(jawab)!='T');

}
void tampil_list()
{
            struct simpul* baca;
            int i;
            baca=awal;
            i=1;

            while(baca!=NULL)

            {
                        cout<<"\nbilangan ke-"<<i<<"yang dibaca :"<<baca->angka;
                        i++;
                        baca=baca->berikut;
            }

}

void hapus_list()

{
            struct simpul*hapus;
            hapus=awal;
            while(hapus!=NULL)
            {
                        awal=hapus->berikut;
                        free(hapus);
                        hapus=awal;
            }
}

Contoh program single linked list non circular tambah di belakang :
#include <stdio.h>
#include <stdlib.h>
#include <constream.h>
#include <ctype.h>
#include <string.h>

struct siswa
{
 char nrp[8],nama[20];
 int umur;
 float ipk;
};

struct simpul
{
 char nrp[8],nama[20];
 int umur;
 float ipk;
 struct simpul *berikut;
};

struct simpul *awal = NULL, *akhir = NULL;
struct siswa mhs;

void tambah_list_dibelakang(struct siswa info);
void isi_list();
void tampil_list();
void hapus_list();

void main()
{
 clrscr();
 isi_list();
 clrscr();
 tampil_list();
 hapus_list();
 getch();
}

void tambah_list_dibelakang(struct siswa info)
{
 struct simpul *baru;

 baru = (struct simpul *) malloc(sizeof(struct simpul));
 strcpy (baru -> nrp,info.nrp);
 strcpy (baru -> nama,info.nama);
 baru -> umur = info.umur;
 baru -> ipk  = info.ipk;

 if (awal == NULL)
 {
  awal = baru;
 }
 else
 {
  akhir -> berikut = baru;
 }
 akhir = baru;
 akhir -> berikut = NULL;
}

void isi_list()
{
 char jawab;

 do
 {
  clrscr();
  cout<<"NRP   : ";cin>>mhs.nrp;
  cout<<"Nama  : ";cin>>mhs.nama;
  cout<<"Umur  : ";cin>>mhs.umur;
  cout<<"IPK   : ";cin>>mhs.ipk;
  tambah_list_dibelakang(mhs);
  cout<<"\nTambah Data [Y/T]? : ";
  cin>>jawab;

 }
 while (toupper(jawab) != 'T');
}

void tampil_list()
{
 struct simpul *baca;
 int i;

 baca = awal;
 i = 1;

 while (baca != NULL)
 {
  cout<<"Data Ke : "<<i<<endl;
  cout<<"NRP     : "<<baca -> nrp<<endl;
  cout<<"Nama    : "<<baca -> nama<<endl;
  cout<<"Umur    : "<<baca -> umur<<endl;
  cout<<"IPK     : "<<baca -> ipk<<endl;
  cout<<endl;
  i++;
  baca = baca -> berikut;
 }
}

void hapus_list()
{
 struct simpul *hapus;

 hapus = awal;
 while (hapus != NULL)
 {
  awal = hapus -> berikut;
  free (hapus);
  hapus = awal;
 }
}

Contoh program single linked list non circular tambah list ditengah :
#include <stdio.h>
#include <constream.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

struct siswa
{
 char nama[20];
 int umur;

};

struct simpul
{
 char nama[20];
 int umur;

 struct simpul *berikut;
};

struct simpul *awal=NULL,*akhir=NULL;
struct siswa mhs;

void tambah_list_belakang(struct siswa info);
void isi_list();
void sisip_list(struct simpul *first,struct siswa info,char posisi[20]);
void sisip_isi_list();
void tampil_list();
void hapus_list();

void main()
{
 clrscr();
 isi_list();

 clrscr();
 tampil_list();
 sisip_isi_list();
 tampil_list();
 hapus_list();
 getch();
}

void tambah_list_dibelakang(struct siswa info)
{
 struct simpul *baru;

 baru=(struct simpul*)malloc(sizeof(struct simpul));
 strcpy(baru->nama,info.nama);
 baru->umur=info.umur;

 if (awal==NULL)
  {
   awal=baru;
  }
 else
  {
   akhir->berikut=baru;
  }
 akhir=baru;

 akhir ->berikut=NULL;
}

void isi_list()
{
 char jawab;

 do
 {
  clrscr();
  cout<<"Nama: ";gets(mhs.nama);
  cout<<"Umur: ";cin>>mhs.umur;

  tambah_list_dibelakang(mhs);

  cout<<"\nTambah Data [Y/T]: ";
  cin>>jawab;
 }
 while (toupper(jawab)!='T');
}
void sisip_list(struct simpul *first,struct siswa info,char posisi[20])
{
struct simpul *bantu,*baru;

baru = new simpul;
strcpy(baru->nama,info.nama);
baru->umur=info.umur;
bantu=first;

do
{
if (strcmp(posisi,bantu->nama)!=0)  {bantu=bantu->berikut;}
}
while (bantu!=NULL && strcmp(posisi,bantu->nama)!=0);

baru->berikut=bantu->berikut;
bantu->berikut=baru;
}


void sisip_isi_list()
{
char cari[20];
struct siswa ganti;

cout<<"\nInput Data Baru :";
cout<<"\nNama :";gets(ganti.nama);
cout<<"\nUmur :";cin>>ganti.umur;
cout<<"\n";
cout<<"\nData Akan Disisipkan Setelah Nama: ";
gets(cari);
sisip_list(awal,ganti,cari);
}

void tampil_list()
{
 struct simpul *baca;
 int i;

 baca=awal;
 i=1;

 while(baca!=NULL)
 {

  cout<<"\nNama : "<<baca->nama;
  cout<<"\nUmur : "<<baca->umur;
  cout<<"\n";
  i++;
  baca=baca->berikut;
 }
}

void hapus_list()
{
 struct simpul *hapus;

 hapus=awal;
 while(hapus!=NULL)
 {
  awal=hapus->berikut;
  free(hapus);
  hapus=awal;
 }
}

Contoh program single linked list non circular untuk menghapus semua list ataupun salah satu dengan menggunakan menu:
#include <constream.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

struct nasabah
{
 char norek[12];
 char nama[25];
 char alamat[50];
 double saldo;
};

struct simpul
{
 char norek[12];
 char nama[25];
 char alamat[50];
 double saldo;
 struct simpul *berikut;
};

struct simpul *awal=NULL, *akhir=NULL;
struct nasabah bank;

void tambah_list_dibelakang(struct nasabah info);
void isi_list();
void sisip_list(struct simpul *first,struct nasabah info,char posisi[20]);
void sisip_isi_list();
void tampil_list();
void hapus_simpul(char info);
void hapus_data();
void hapus_list();
void menu();

void main()
{
 clrscr();
 menu();
 getch();
}
void menu()
{
 int pil;
 clrscr();
 cout<<"Programmer : Shandy Johan_6311171"<<endl<<endl;
 cout<<"Pilih Transaksi  : "<<endl;
 cout<<"            1. Isi List"<<endl;
 cout<<"            2. Sisip List"<<endl;
 cout<<"            3. Tampil List"<<endl;
 cout<<"            4. Hapus Salah Satu"<<endl;
 cout<<"            5. Hapus Semua List"<<endl;
 cout<<"            6. Exit"<<endl<<endl;
 cout<<"Tentukan Pilihan : ";
 cin>>pil;
 switch (pil)
 {
  case 1:
       isi_list();
       break;
  case 2:
       sisip_isi_list();
       break;
  case 3:
       tampil_list();
       break;
  case 4:
       hapus_data();
       break;
  case 5:
       hapus_list();
       break;
  case 6:
       clrscr();
       gotoxy(21,13);cout<<"Terima Kasih Telah Menggunakan Program Ini";
       break;
 }
}

void isi_list()
{
 char jawab;

 do
 {
  clrscr();
  cout<<"No Rekening : ";
  cin>>bank.norek;
  cout<<"Nama        : ";
  cin>>bank.nama;
  cout<<"Alamat      : ";
  cin>>bank.alamat;
  cout<<"Saldo Awal  : ";
  cin>>bank.saldo;
  tambah_list_dibelakang(bank);
  cout<<"\n\nTambah Data [Y/T] : ";
  cin>>jawab;
 }
 while (toupper(jawab)!='T');
 menu();
}

void tambah_list_dibelakang(struct nasabah info)
{
 struct simpul *baru;

 baru = (struct simpul *) malloc (sizeof(struct simpul));
 strcpy (baru -> norek,info.norek);
 strcpy (baru -> nama,info.nama);
 strcpy (baru -> alamat,info.alamat);
 baru -> saldo = info.saldo;

 if (awal == NULL)
 {
  awal = baru;
 }
  else
  {
   akhir -> berikut = baru;
  }
 akhir = baru;
 akhir -> berikut = NULL;
}

void tampil_list()
{
 clrscr();
 struct simpul *baca;
 int i;

 baca = awal;
 i = 1;

 while (baca != NULL)
 {
  cout<<"Data Ke : "<<i<<endl;
  cout<<"No Rekening  : "<<baca -> norek<<endl;
  cout<<"Nama         : "<<baca -> nama<<endl;
  cout<<"Alamat       : "<<baca -> alamat<<endl;
  cout<<"Saldo Awal   : "<<baca -> saldo<<endl;
  cout<<endl;
  i++;
  baca = baca -> berikut;
 }
 getch();
 menu();
}

void hapus_list()
{
 struct simpul *hapus;
 hapus = awal;
 while (hapus != NULL)
 {
  awal = hapus -> berikut;
  free(hapus);
  hapus = awal;
 }
 menu();
}


void sisip_list(struct simpul *first, struct nasabah info, char posisi[20])
{
 struct simpul *bantu,*baru;

 baru = new simpul;
 strcpy (baru -> norek,info.norek);
 strcpy (baru -> nama,info.nama);
 strcpy (baru -> alamat,info.alamat);
 baru-> saldo = info.saldo;
 bantu = first;

 do
 {
  if (strcmp(posisi,bantu->norek)!=0)
  {
   bantu = bantu->berikut;
  }
 }
 while (bantu !=NULL & strcmp(posisi,bantu->norek)!=0);

 baru->berikut = bantu -> berikut;
 bantu -> berikut = baru;
}

void sisip_isi_list()
{
 char cari[20];
 struct nasabah ganti;
  clrscr();
  cout<<"Input Data Baru"<<endl;
  cout<<"No Rekening : ";
  cin>>ganti.norek;
  cout<<"Nama        : ";
  cin>>ganti.nama;
  cout<<"Alamat      : ";
  cin>>ganti.alamat;
  cout<<"Saldo Awal  : ";
  cin>>ganti.saldo;
  cout<<endl;
  cout<<"Data Akan Disisipkan Setelah No Rekening : ";
  gets(cari);
  sisip_list(awal,ganti,cari);
  menu();
}

void hapus_simpul(char info[20])
{
 struct simpul *bantu,*hapus;

 if (awal==NULL) { cout<<"\n Data List Kosong ";}
 else
 {
  if (strcmp(awal->norek,info)==0)
  {
   hapus=awal;
   awal=hapus->berikut;
   free(hapus);
  }
   else
   {
    bantu=awal;
    while ((strcmp(info,bantu->berikut->norek)!=0) && (bantu->berikut!=NULL))
    {
     bantu=bantu->berikut;
    }
    hapus=bantu->berikut;
    if (hapus!=NULL)
    {
     if (hapus!=akhir) { bantu->berikut=hapus->berikut;}
     else
     {
      akhir=bantu;
      akhir->berikut=NULL;
     }
     free(hapus);
    }
   }
  }
}


void hapus_data()
{
 char cari[20];
 char jawab;

 clrscr();

 cout<<"\nAda data yang akan dihapus Y/T :";cin>>jawab;
 if (toupper(jawab)=='Y')
 {
  cout<<"\nNo.Rekening yang akan dihapus :";
  gets(cari);
  hapus_simpul(cari);
  menu();
 }
}

Single Linked List Circular

1.     Single Linked List Circular
Single Linked List Circular adalah Single Linked List yang pointer nextnya menunjuk pada dirinya sendiri. Jika Single Linked List tersebut terdiri dari beberapa node, 
maka pointer next pada node terakhir akan menunjuk ke node terdepannya.
Pengertian: 
Single : artinya field pointer-nya hanya satu buah saja dan satu arah. 
Circular : artinya pointer next-nya akan menunjuk pada dirinya sendiri sehingga berputar

Ilustrasi Single Linked List Circular 
- Setiap node pada linked list mempunyai field yang berisi pointer ke node
  berikutnya, dan juga memiliki field yang berisi data. 
- Pada akhir linked list, node terakhir akan menunjuk ke node terdepan 
  sehingga linked list tersebut berputar. Node terakhir akan menunjuk lagi 
  ke head.

PEMBUATAN SINGLE LINKED LIST CIRCULAR 
Deklarasi node 
Dibuat dari struct berikut ini: 
typedef struct TNode{ 
int data; 
TNode *next; 
};

Penjelasan: 
- Pembuatan struct bernama TNode yang berisi 2 field, yaitu field data 
  bertipe integer dan field next yang bertipe pointer dari TNode 
- Setelah pembuatan struct, buat variabel haed yang bertipe pointer dari 
  TNode yang berguna sebagai kepala linked list.

Pembentukan node baru 
Digunakan keyword new yang berarti mempersiapkan sebuah node baru 
berserta alokasi memorinya. 

TNode *baru; 
baru = new TNode; 
baru->data = databaru; 
baru->next = baru; 

SINGLE LINKED LIST CIRCULAR MENGGUNAKAN HEAD 
- Dibutuhkan satu buah variabel pointer: head 
- Head akan selalu menunjuk pada node pertama 

Deklarasi Pointer Penunjuk Kepala Single Linked List 
Manipulasi linked list tidak bisa dilakukan langsung ke node yang dituju, 
melainkan harus melalui node pertama dalam linked list. Deklarasinya sebagai berikut: 

TNode *head; 

Fungsi Inisialisasi Single LinkedList 
void init(){ 
head = NULL; 
} 

Function untuk mengetahui kosong tidaknya Single LinkedList 
int isEmpty(){ 
if(head == NULL) return 1; 
else return 0; 
} 

PENAMBAHAN DATA 
Penambahan data di depan 
Penambahan node baru akan dikaitan di node paling depan, namun pada saat
pertama kali (data masih kosong), maka penambahan data dilakukan pada 
head nya. 
Pada prinsipnya adalah mengkaitkan data baru dengan head, kemudian head
akan menunjuk pada data baru tersebut sehingga head akan tetap selalu 
menjadi data terdepan. Untuk menghubungkan node terakhir dengan node 
terdepan dibutuhkan pointer bantu. 

void insertDepan(int databaru){ 
TNode *baru,*bantu; 
baru = new TNode; 
baru->data = databaru; 
baru->next = baru; 

if(isEmpty()==1){ 
head=baru; 
head->next=head; 
} 
else { 
bantu = head; 
while(bantu->next!=head){ 
bantu=bantu->next; 
} 
baru->next = head; 
head = baru; 
bantu->next = head; 
} 
cout<<"Data masuk\n"; 
} 

Penambahan data di belakang Penambahan data dilakukan di belakang, namun pada saat pertama kali data langsung ditunjuk pada head-nya. Penambahan di belakang lebih sulit karena kita membutuhkan pointer bantu untuk mengetahui data terbelakang, kemudian dikaitkan dengan data baru. Untuk mengetahui data terbelakang perlu digunakan perulangan.

void insertBelakang (int databaru) 
{ 
TNode *baru,*bantu; 
baru = new TNode; 
baru->data = databaru; 
baru->next = baru; 
if(isEmpty()==1){ 
head=baru; 
head->next=head; 
} 
else { 
bantu = head; 
while(bantu->next != head){ 
bantu=bantu->next; 
} 
bantu->next = baru; 
baru->next = head; 
} 
cout<<"Data masuk\n"; 
} 

“Bagaimana dengan penambahan di tengah?” 

MENAMPILKAN DATA 
Function untuk menampilkan isi single linked list 
void tampil(){ TNode *b; 
b = head; 
if(isEmpty()==0) 
{ 
do 
{ 
cout<data<<" "; 
b=b->next; 
} 
while(b!=head); 
cout<<<"Masih kosong\n"; 
} 

- Function di atas digunakan untuk menampilkan semua isi list, di mana linked list ditelusuri satu-persatu dari awal node sampai akhir node. Penelusuran ini dilakukan dengan menggunakan suatu variabel node bantu, karena pada prinsipnya variabel node head yang menjadi tanda awal list tidak boleh berubah/berganti posisi. 
- Penelusuran dilakukan terus sampai node terakhir ditemukan menunjuk ke head lagi. Jika belum sama dengan head, maka node bantu akan berpindah ke node selanjutnya dan membaca isi datanya dengan menggunakan field next sehingga dapat saling berkait. 
- Jika head masih NULL berarti data masih kosong! 

PENGHAPUSAN DATA 
Function untuk menghapus data terdepan 

void hapusDepan () 
{ TNode *hapus,*bantu; 
if (isEmpty()==0) 
{ 
int d; 
hapus = head; d = head->data; 
if(head->next != head){ 
bantu = head; 
while(bantu->next!=head){ 
bantu=bantu->next; 
} 
head = head->next; 
delete hapus; 
bantu->next = head; 
}else{ 
head=NULL; 
} 
cout<<<" terhapus\n"; 
} 
else cout<<"Masih kosong\n"; 
} 

- Function di atas akan menghapus data teratas (pertama) yang ditunjuk oleh head  pada linked list 
- Penghapusan node tidak boleh dilakukan jika keadaan node sedang ditunjuk oleh pointer, maka harus ditampung dahulu pada variabel hapus dan barulah kemudian menghapus variabel hapus dengan menggunakan perintah delete. 
- Sebelum data terdepan dihapus, head harus ditunjukkan ke data sesudahnya  terlebih dahulu sehingga data setelah head lama akan menjadi head baru (data terdepan yang baru). 
- Jika head masih NULL maka berarti data masih kosong! 

Penghapusan data di belakang: 

void hapusBelakang() 
{ TNode *hapus,*bantu; 
if (isEmpty()==0) 
{ 
int d; 
hapus = head; 
if(head->next == head){ 
head = NULL; 
} 
else 
{ 
bantu = head; 
while(bantu->next->next != head){ 
bantu = bantu->next; 
} 
hapus = bantu->next; 
d = bantu->data; 
bantu->next = head; 
delete hapus; 
} 
cout<<<" terhapus\n"; 
} 
else 
cout<<"Masih kosong\n"; 
} 

- Membutuhkan pointer bantu dan hapus. 
- Pointer hapus digunakan untuk menunjuk node yang akan dihapus, dan pointer bantu digunakan untuk menunjuk node sebelum node yang dihapus. 
- Pointer bantu akan digunakan untuk menunjuk ke nilai NULL. 
- Pointer bantu akan selalu bergerak bersama dengan pointer hapus tapi letak pointer bantu harus selalu dibelakang pointer hapus. 

Function untuk menghapus semua elemen Linked List 

void clear(){ TNode *bantu,*hapus; 
bantu = head; 
while(bantu->next!=head){ 
hapus = bantu; 
bantu = bantu->next; 
delete hapus; 
} 
head = NULL; 
} 

SINGLE LINKED LIST MENGGUNAKAN HEAD DAN TAIL 
- Dibutuhkan dua buah variabel pointer: head dan tail 
- Head akan selalu menunjuk pada node pertama, sedangkan tail akan 
selalu menunjuk pada node terakhir. 

Inisialisasi LinkedList 

TNode *head, *tail; 

Fungsi Inisialisasi LinkedList 

void init(){ 
head = NULL; 
tail = NULL; 
} 

Function untuk mengetahui kosong tidaknya LinkedList 

int isEmpty(){ 
if(tail == NULL) return 1; 
else return 0; 
} 

PENAMBAHAN DATA 
Pengkaitan node baru ke linked list di depan 
Penambahan data baru di depan akan selalu menjadi head. 

void insertDepan(int databaru){ 
TNode *baru; 
baru = new TNode; 
baru->data = databaru; 
baru->next = baru; 
if(isEmpty()==1){ 
head=baru; 
tail=baru; 
head->next=head; 
tail->next=tail; 
} 
else { 
baru->next = head; 
head = baru; 
tail->next = head; 
} 
cout<<"Data masuk\n"; 
} 

Penambahan Data di belakang Pada penambahan data di belakang, data akan selalu dikaitkan dengan tail, karena tail terletak di node paling belakang. Setelah dikaitkan dengan node baru, maka node baru tersebut akan menjadi tail. 

void tambahBelakang(int databaru){ TNode *baru; 
baru = new TNode; 
baru->data = databaru; 
baru->next = baru; 
if(isEmpty()==1){ 
head=baru; 
tail=baru; 
head->next=head; 
tail->next=tail; 
} 
else 
{ 
tail->next = baru; 
tail = baru; 
tail->next = head; 
} 
cout<<"Data masuk\n"; 
} 

Kelebihan dari Single Linked List dengan Head & Tail adalah pada penambahan data di belakang, hanya dibutuhkan tail yang mengikat node baru saja tanpa harus menggunakan perulangan pointer bantu. 

Function untuk menampilkan isi linked list: 

void tampil(){ TNode *b; 
b = head; if(isEmpty()==0) 
{ 
do 
{ cout<data<<" "; 
b=b->next; 
} 
while(b!=tail->next); 
cout<<<"Masih kosong\n"; 
} 

Pada prinsipnya sama dengan function tampil sebelumnya. 

Function untuk menghapus data di depan 

void hapusDepan(){ TNode *hapus; 
if (isEmpty()==0){ int d; 
hapus = head; 
d = head->data; 
if(head != tail){ 
hapus = head; 
head = head->next; 
tail->next = head; 
delete hapus; 
}else{ 
head=NULL; 
tail=NULL; 
} 
cout<<<" terhapus\n"; 
} 
else cout<<"Masih kosong\n"; 
} 

- Function di atas akan menghapus data terdepan (pertama) yang ditunjuk oleh head pada linked list 
- Penghapusan node tidak boleh dilakukan jika keadaan node sedang ditunjuk oleh pointer, maka harus dilakukan penunjukkan terlebih dahulu dengan variabel hapus pada head, kemudian dilakukan pergeseran ke node berikutnya sehingga data setelah head menjadi head baru, kemudian menghapus variabel hapus dengan menggunakan perintah delete. 
- Jika tail masih NULL maka berarti data masih kosong! 

Function untuk menghapus data di belakang: 

Dengan menggunakan Single Linked List ber-Head dan Tail, pengahapusan data di belakang akan mudah dilakukan, tidak seperti pada Single Linked List hanya ber-Head saja. 

void hapusBelakang(){ TNode *hapus,*bantu; 
if (isEmpty()==0){ int d; 
if(head == tail){ d = tail->data; 
head = NULL; 
tail = NULL; 
} 
else 
{ 
bantu = head; 
while(bantu->next != tail){ 
bantu = bantu->next; 
} 
hapus = tail; 
tail = bantu; 
d = hapus->data; 
tail->next = head; 
delete hapus; 
} 
cout<<<" terhapus\n"; 
} 
else cout<<"Masih kosong\n"; 
} 

- Function di atas akan menghapus data terbelakang (terakhir) yang ditunjuk oleh tail pada linked list 
- Penghapusan node tidak boleh dilakukan jika keadaan node sedang ditunjuk oleh pointer, maka harus dilakukan penunjukkan terlebih dahulu dengan variabel hapus pada tail, kemudian dibutuhkan pointer bantu untuk membantu pergeseran dari head ke node berikutnya sampai sebelum tail, sehingga tail dapat ditunjukkan ke bantu tersebut, dan bantu tersebut akan menjadi tail yang baru. Setelah itu hapus variabel hapus dengan menggunakan perintah delete. 
- Jika tail masih NULL maka berarti data masih kosong! 

Function untuk menghapus semua elemen LinkedList 

void clear(){ TNode *bantu,*hapus; 
if(isEmpty() == 0){ bantu = head; 
while(bantu->next!=head){ 
hapus = bantu; 
bantu = bantu->next; 
delete hapus; 
} 
head = NULL; 
tail = NULL; 
} 
} 

- Menggunakan pointer bantu yang digunakan untuk bergerak sepanjang 
list, dan menggunakan pointer hapus yang digunakan untuk menunjuk 
node-node yang akan dihapus. 
- Pada saat pointer hapus menunjuk pada node yang akan dihapus, pointer 
bantu akan bergerak ke node selanjutnya, dan kemudian pointer hapus 
akan didelete.



Graph


Struktur Data Graph

Struktur data yang berbentuk network/jaringan, hubungan antar elemen adalah many-to-many

Keterhubungan dan jarak tidak langsung antara dua kota = data keterhubungan langsung dari kota-kota lainnya yang memperantarainya.Penerapan struktur data linear atau hirarki pada masalah graph dapat dilakukan tetapi kurang efisien. Struktur data graph secara eksplisit menyatakan keterhubungan ini sehingga pencariannya langsung (straightforward) dilakukan pada strukturnya sendiri.


1. Struktur Data Linear = keterhubungan sekuensial antara entitas data


2. Struktur Data Tree = keterhubungan hirarki


3. Struktur Data Graph = keterhubungan tak terbatas antara entitas data.


Contoh graph :

"Informasi topologi jaringan dan keterhubungan antar kota-kota"

 

Graph terdiri dari himpunan verteks (node) dan himpunan sisi (edge,arc). Verteks menyatakan entitas-entitas data dan sisi menyatakan keterhubungan antara verteks.


Notasi matematis graph G adalah :

G = (V, E)

Sebuah sisi antara verteks x dan y ditulis {x, y}.

Subgraph : graph yang merupakan suatu subset (bagian) graph yang connected

Graph H = (V1, E1) disebut subgraph dari graph G jika V1 adalah himpunanbagian dari V dan E1 himpunan bagian dari E.


Jenis Graph


a. Directed Graph (Digraph)

Jika sisi-sisi graph hanya berlaku satu arah. Misalnya : {x,y} yaitu arahx ke y, bukan dari y ke x; x disebut origin dan y disebut terminus. 

Secara notasi sisi digraph ditulis sebagai vektor (x, y).

 

Contoh Digraph G = {V, E} :

 V = {A, B, C, D, E, F, G, H, I,J, K, L, M}

 E = {(A,B),(A,C), (A,D), (A,F), (B,C), (B,H), (C,E), (C,G),

      (C,H), (C,I), (D,E),(D,F), (D,G), (D,K), (D,L), (E,F),

      (G,I), (G,K), (H,I), (I,J), (I,M), (J,K),(J,M), (L,K),

      (L,M)}.


b. Graph Tak Berarah (Undirected Graph atau Undigraph)

Setiap sisi {x, y} berlaku pada kedua arah: baik x ke y maupun y ke x.

Secara grafis sisi pada undigraph tidak memiliki mata panah dan secara notasional menggunakan kurung kurawal.


Contoh Undigraph G = {V, E}

 V = {A, B, C, D, E, F, G, H, I,J, K, L, M}

 E = { {A,B},{A,C}, {A,D}, {A,F}, {B,C}, {B,H}, {C,E}, {C,G},

     {C,H}, {C,I}, {D,E},{D,F}, {D,G}, {D,K}, {D,L}, {E,F},

     {G,I}, {G,K}, {H,I}, {I,J}, {I,M}, {J,K},{J,M}, {L,K},

     {L,M}}.

Khusus graph, undigraph bisa sebagai digraph (panah di kedua ujung edge berlawanan) 

Struktur data linear maupun hirarkis adalah juga graph. Node - node pada struktur linear ataupun hirarkis adalah verteks - verteks dalam pengertian graph dengan sisi-sisinya menyusun node-node tersebut secara linear atau hirarkis.

Struktur data linear adalah juga tree dengan pencabangan pada setiap node hanya satu atau tidak ada. Linear single linked list (digraph), linear 2-way linked list (undigraph).

Selasa, 17 Juli 2012

Pointer


Pengertian Pointer

Dalam ilmu komputer, pointer adalah tipe data bahasa pemrograman yang nilainya mengacu untuk menunjuk langsung nilai lain yang tersimpan di tempat lain dalam suatu memori komputer menggunakan alamat yang ada. Untuk bahasa pemrograman tingkat tinggi, pointer secara efektif dapat mengambil tempat pada general purpose registers di bahasa tingkat rendah seperti bahasa assembly atau kode mesin, tetapi bila memori tersedia. 

Pointer adalah implementasi sederhana, lebih konkret tentang tipe data referensi yang lebih abstrak. Beberapa bahasa mendukung beberapa jenis pointer, walaupun ada yang memiliki lebih banyak pembatasan penggunaannya dari pada yang lain. Sebagai analogi, sebuah nomor halaman dalam buku dapat dianggap sebagai pointer ke halaman yang sesuai; dereferencing seperti pointer akan dilakukan dengan membalik ke halaman dengan nomor halaman yang diberikan. 

Pointer dapat meningkatkan kinerja data secara signifikan agar operasi berulang seperti traversing string, tabel lookup, tabel kontrol dan struktur pohon. Secara khusus, sering jauh lebih efisien dalam waktu dan space untuk pointer dari pada menggunakan variable tipe data biasa. 

Pointer juga digunakan untuk menyimpan alamat dari titik masuk untuk memanggil subrutin dalam pemrograman prosedural dan untuk run-time penghubung ke dynamic link libraries (DLL). Dalam pemrograman berorientasi objek, pointer ke fungsi yang digunakan untuk mengikat/menjilid method, ini sering disebut tabel method virtual.

Sementara "pointer" telah digunakan untuk merujuk pada referensi yang ada pada umumnya, hal ini berlaku lebih baik bagi struktur data yang secara eksplisit memungkinkan antarmuka (interface) pointer untuk dimanipulasi (secara aritmetik melalui aritmetik pointer) sebagai alamat memori. Karena pointer memungkinkan akses yang baik dilindungi maupun tidak dilindungi ke memori yang dituju. 

Pointer primitif adalah pointer sering disimpan dalam format yang sama dengan integer. Namun, mencoba untuk dereference atau "mencari" pointer yang nilainya tidak pernah menjadi alamat memori yang valid akan menyebabkan program menjadi crash. 

Deskripsi Formal: 
Dalam ilmu komputer, pointer adalah macam referensi. Sebuah data primitive (primitive) adalah setiap datum yang dapat dibaca dari atau ditulis ke memori komputer menggunakan satu akses memori (misalnya, kedua byte dan kata (word) yang primitif). 


Sebuah data agregat (aggregate) adalah sekelompok data primitif yang logis berdekatan di memori dan yang dipandang secara kolektif sebagai satu datum (misalnya, agregat bisa saja 3 byte logis berdekatan, maka nilai-nilai itu lah yang mewakili 3 koordinat titik di dalam ruang memori), ketika seluruh agregat yang terdiri dari jenis primitive yang sama, agregat dapat disebut sabagai sebuah array, dalam arti, multi-byte primitif adalah array dari byte.

Dalam konteks definisi ini, byte adalah primitif terkecil, masing-masing menentukan alamat memori byte yang berbeda. Alamat memori dari byte pertama pada sebuah datum dianggap sebagai alamat memori (atau base alamat memori) dari seluruh datum. 

Sebuah pointer memori adalah primitive, nilai yang dimaksudkan untuk digunakan sebagai alamat memori itu disebut sebagai pointer petunjuk ke alamat memori. Hal ini juga disebut bahwa pointer menunjuk ke datum [dalam memori] ketika nilai pointer berupa alamat memori datum itu.

Secara lebih umumnya, pointer adalah jenis data referensi, dan agar memperoleh  pointer dereference maka datum pointer disimpan di lokasi yang berbeda di dalam memori. Fitur yang membedakan pointer dengan jenis referensi lain adalah nilai pointer yang dimaksud  agar ditafsirkan sebagai alamat memori, yang merupakan konsep 'tingkat rendah'. 

Saat membuat struktur data seperti daftar, deret dan percabangan, perlu memiliki pointer untuk membantu mengelola bagaimana struktur dapat diimplementasikan dan dikendalikan. Contoh umum dari pointer adalah start pointer, end pointer, dan stack pointer. Pointer ini dapat menjadi absolute (alamat fisik yang sebenarnya atau alamat virtual di memori virtual) atau relative (sebuah offset dari alamat awal absolute ("dasar") yang biasanya menggunakan bit yang lebih sedikit dari pada alamat lengkap, tetapi biasanya juga akan membutuhkan satu tambahan operasi aritmatika untuk menyelesaikannya).

Dua byte offset, berisi 16-bit unsigned integer, dapat digunakan untuk menyediakan pengalamatan relative sampai dengan 64 kilobyte struktur data. Secara umum, meskipun, skema seperti itu banyak masalah, dan untuk kemudahan bagi programmer maka ruang alamat datar biasanya lebih disukai.

Sebuah byte offset, seperti nilai ASCII karakter heksadesimal dapat digunakan untuk menunjuk nilai integer alternatif dalam array. Dengan cara ini, karakter dapat sangat efisien diterjemahkan dari 'data mentah' ke indeks sekuensial dapat digunakan dan kemudian ke alamat absolut tanpa menggunakan tabel lookup. 

Digunakan dalam mengontrol tabel 
Kontrol tabel digunakan untuk mengontrol aliran program (program flow), biasanya membuat ekstensif menggunakan pointer. Pointer biasanya tertanam dalam sebuah entry tabel. Misalnya, digunakan untuk menyimpan entry point bagi subrutin yang akan dijalankan, dan berdasarkan kondisi tertentu yang didefinisikan dalam entri tabel yang sama. 

Namun pointer  hanya dapat berupa indeks untuk memisahkan data yang lain tetapi terikat, tabel terdiri dari suatu array dari alamat yang aktual atau alamat sendiri (tergantung pada konstruksi bahasa pemrograman yang tersedia). 

Pointer juga dapat digunakan untuk titik (kembali) ke entri tabel sebelumnya (seperti dalam pengolahan loop) atau maju melewatibeberapa entri tabel (seperti pada switch atau "awal" keluar dari loop). 

Abstraksi pointer yang sangat tipis di atas merupakan kemampuan pengalamatan yang dikembangkan dengan arsitektur paling modern. Dalam skema sederhana, alamat atau indeks numerik, ditugaskan bagi setiap unit memori dalam sistem, di mana unit ini biasanya baik byte atau kata (word), secara efektif dapat mengubah semua memori ke array yang sangat besar. Kemudian, jika kita memiliki suatu alamat, sistem itu menyediakan operasi untuk mengambil nilai yang tersimpan dalam unit memori pada alamat (biasanya menggunakan register tujuan umum didalam mesin yang digunakan). 

Dalam kasus biasa, pointer itu cukup besar untuk menampung alamat lebih dari beberapa unit memori yang berada di dalam sistem. Ini memperkenalkan kemungkinan bahwa program mungkin berusaha untuk mengakses alamat bila tidak ada unit memori, baik karena memori tidak cukup dipasang (yaitu di luar jangkauan memori yang tersedia) atau arsitektur tidak mendukung alamat tersebut. Kasus pertama mungkin, dalam platform tertentu seperti arsitektur Intel x86, disebut kesalahan segmentasi (segfault). Kasus kedua adalah mungkin dalam implementasi pada AMD64, di mana pointer yang memiliki panjang 64 bit dan alamat hanya memperpanjang sampai 48 bit. Disini pointer harus sesuai dengan aturan-aturan tertentu (alamat kanonik), jadi jika pointer nonkanonik adalah dereferenced, akan berakibat prosesor melakukan kesalahan perlindungan umum (general protection fault).

Di sisi lain, beberapa sistem memiliki lebih banyak unit memori dari pada alamat. Dalam hal ini, skema yang lebih kompleks seperti segmentasi memori atau paging dikelola untuk menggunakan bagian yang berbeda dari memori pada waktu yang berbeda pula. Inkarnasi terakhir dari arsitektur x86 mendukung hingga 36 bit dari alamat memori fisik, yang dipetakan ke ruang alamat 32-bit linear melalui mekanisme paging PAE. Jadi, hanya 1 / 16 dari total memori yang mungkin dapat diakses pada suatu waktu. Contoh lain dalam kelompok komputer yang sama adalah 16-bit dalam keadaan terlindungi dari prosesor 80286 yang meskipun mempunyai 16 MiB memori fisik, dapat mengakses hingga 1 GB dari memori virtual, namun kombinasi dari 16-bit alamat dan segmen register dapat mengakses lebih dari 64 KiB dalam satu struktur data rumit. Beberapa pembatasan aritmetik pointer ANSI mungkin memiliki model memori tersegmentasi dari kelompok prosesor ini.

Dalam rangka untuk mengembangkan interface yang konsisten, beberapa arsitektur menyediakan I / O yang dipetakan ke dalam memori, yang memungkinkan beberapa alamat untuk menuju ke unit memori sementara yang lain mengacu pada register perangkat perangkat lain di komputer. Ada konsep analog seperti file offset, indeks array, dan referensi object remote yang melayani beberapa tujuan yang sama sebagai alamat untuk jenis object lainnya. 

Pointer secara langsung didukung tanpa pembatasan dalam bahasa seperti PL / I, C, C++, Pascal, dan kebanyakan bahasa perakitan. Ketika berhadapan dengan array, operasi pencarian kritis biasanya perhitungan alamat  disebut tahap perhitungan alamat yang melibatkan pembentukan sebuah array. 

Dalam struktur data lain, seperti daftar terhubung (linked list), pointer digunakan sebagai referensi secara eksplisit yang mengikat salah satu bagian dari struktur yang lain. Pointer digunakan untuk menumpangi parameter bagi referensi. Hal ini berguna jika programmer mengingin modifikasi fungsi untuk parameter, untuk dapat dilihat ke pemanggilan fungsi itu. Ini juga berguna untuk menampikan nilai hasil perkalian dari dalam fungsi yang telah dibuat.

Pointer juga dapat digunakan untuk mengalokasikan atau DEALLOCATE variabel dinamis dan array dalam memori. Karena variable akan sering menjadikan memori penuh setelah selasai ngerjakan perintah, itu bisa menjadi pemborosan memori bila kita menyimpannya, dan oleh karena itu praktik yang baik untuk DEALLOCATE itu (menggunakan referensi pointer asli) ketika tidak lagi diperlukan. Kegagalan untuk melakukannya dapat mengakibatkan kehabisan memori (di mana memori bebas yang tersedia akan secara bertahap berkurang atau dalam kasus yang parah dengan secara cepat akan penuh). 

Menurut Frieyadie. 2007. Edisi Revisi Buku Pemrograman C++ dengan Borland C++ 5.02. 
Pointer adalah sebuah variabel yang berisi alamat lain. Suatu pointer dimaksudkan untuk menunjukan ke suatu alamat memori sehingga alamat dari suatu variabel dapat diketahui dengan mudah. 
Contoh Program:
#include <stdio.h>         //Mengakses file pada library stdio.h
#include <stdlib.h>        //Mengakses file pada library stdlib.h
int main (void){             //Fungsi main yang harus ada dalam sebuah program C
   int A = 5, H;
   int *ptrA, *ptrH;         //Deklarasi pointer sebagai integer
   ptrA = &A;                //Alamat lokasi memori dari variabel A disimpan pada ptrA
   H = *ptrA;                 //Nilai data yang alamat lokasi memorinya disimpan pada ptrA, 
                                        disimpan di variabel H
   ptrH = &H;                //Alamat lokasi memori dari variabel H disimpan pada ptrH
                                     // %x menampilkan nilai hexa
  printf("A=%d\n &A=%x \n ptrA=%x \n *ptrA=%d", A, &A, ptrA, *ptrA);   
  printf("\n\nH=%d\n &H=%X\n ptrH=%X\n *ptrH=%d\n\n", H, &H, ptrH,*ptrH);
system ("pause");           //File yang terdapat pada stdlib.h
return (0);                     //Nilai balikan fungsi main() adalah 0
}
Arti pointer dalam bahasa sehari-hari adalah putunjuk atau dapat dikatakan sebagai penentu atau dapat diartikan sebagai tipe data yang nilainya mengarah pada nilai yang terdapat pada sebuah area memori (alamat memori).Namun dalam bahasa C, Pointer bisa berfungsi sebagai variabel array berarti pointer sebagai penunjuk elemen array ke-0 dalam variabel C. 

Kegunaan Pointer Di C++ : 
Kegunaan pointer yang utama adalah untuk menyimpan alamat memori dari sebuah variabel (data type atau object dari class), menyimpan alamat dari sebuah fungsi (function pointer) dan dapat berfungsi untuk  mengirimkan “Parameter yang berupa variabel” ke dalam fungsi, artinya nilai variabel bisa diubah di dalam fungsi serta dapat membuat variabel dinamis. 

Tipe Data Pointer : 
Tipe_data merupakan tipe dari data yang ditunjuk, bukan tipe dari pointer- nya. Contoh : 
1. Mensubstitusikan address sebuah variabel ke pointer dengan memakai address operator & 
    int x; 
    int *ptr; 
    ptr = &x; 

2. Mensubstitusikan address awal sebuah array ke pointer 
    char t[5]; char *ptr; ptr = t; 

3. Mensubstitusikan address salah satu elemen array dengan address operator 
    char t[5] ; char *ptr; ptr = &t[3]; 

4. Mensubstitusikan address awal character string ke pointer char 
    char *ptr; 
    ptr = "jakarta" 

5. Mensubstitusikan NULL pada pointer. 
NULL ada pointer kosong, menunjukkan suatu status dimana pointer itu belum diinisialisasikan dengan sebuah address tertentu. 

Operator Pointer :
Ada 2 operator pointer yang dikenal secara luas, yaitu operator & dan operator *. 

Operator & 
Operator & merupakan operator alamat. Pada saat pendeklarasian variable, user tidak diharuskan menentukan lokasi sesungguhnya pada memory, hal ini akan dilakukan secara otomatis oleh kompiler dan operating sysem pada saat run-time. Jika ingin mengetahui dimana suatu variable akan disimpan, dapat dilakukan dengan memberikan tanda ampersand (&) didepan variable , yang berarti "address of". Contoh : ted = &input; 

Penulisan tersebut berarti akan memberikan variable ted alamat dari variable input. Karena variabel input diberi awalan karakter ampersand (&), maka yang menjadi pokok disini adalah alamat dalam memory, bukan isi variable. 

Misalkan input diletakkan pada alamat 1776 kemudian dituliskan instruksi sbb : 
input = 25;  fred = input; ted = &input; 

Operator * 
Operator * merupakan operator reference. Dengan menggunakan pointer,kita dapat mengakses nilai yang tersimpan secara langsung dengan memberikan awalan operator asterisk (*) pada identifier pointer, yang berarti "value pointed by". Contoh : 
beth = *ted; 
(dapat dikatakan:"beth sama dengan nilai yang ditunjuk oleh ted") beth = 25, karena ted dialamat 1776, dan nilai yang berada pada alamat 1776 adalah 25. 

Macam – macam Pointer 
  1. Pointer Bertipe Void
    Pada C++ terdapat pointer yang dapat menunjuk ke tipe data apapun, pointer semacam ini dideklarasikan dengan tipe void sehingga sering dikenal dengan istilah Void Pointer. Berikut ini contoh listing program yang menggunakan void pointer.
  2. Pointer Aritmetika
    Elemen-elemen array biasanya diakses melalui indeksnya, sebenarnya ada cara lain yang lebih efisien, yaitu dengan menggunakan pointer. Pointer semacam ini disebut dengan istilah pointer aritmetika. Konsep dasar dari pointer aritmetika ini adalah melakukan operasi aritmetika terhadap variabel yang bertipe pointer.
  3. Pointer NULL
    Pada saat program dijalankan, pointer akan menunjuk ke alamat acak pada memori, sehingga diperlukan inisialisasi agar hal tersebut tidak terjadi. Dalam C++ terdapat sebuah cara untuk membuat pointer tidak menunjuk ke alamat manapun, yaitu dengan mengisikan pointer tersebut dengan nilai NULL. Karena hal inilah maka pointer tersebut sering dinamakan pointer NULL (NULL Pointer).Se¬bagai contoh kita mempunyai pointer p, dan kita ingin melakukan inisialisasi pada pointer tersebut dengan nilai NULL, maka sintaknya adalah  P=NULL; 

DEKLARASI POINTER

Seperti halnya variabel yang lain, variabel pointer juga harus dideklarasikan terlebih dahulu sebelum digunakan.
Bentuk Umum :
                              Tipe_data *nama_pointer;

//Contoh9_1
int *px;
char *sh;
Contoh Program :
#include “IOSTREAM.h”
#include “conio.h”
void main()
{ int x, y; /* x dan y bertipe int */
int *px; /* px pointer yang menunjuk objek */
clrscr();
x = 87;
px = &x; /* px berisi alamat dari x */
y = *px; /* y berisi nilai yang ditunjuk px */
cout<<“Alamat x =”<<&x <<\n”;
cout<<“Isi px = \n”, px);
cout<<“Isi x = \n”, x);
cout<<“Nilai yang ditunjuk oleh px = \n”, *px);
cout<<“Nilai y = \n”, y);
getch();
}

Operasi-operasi Pointer 
  1. Operasi Penugasan
    Suatu variabel pointer seperti halnya variabel yang lain, juga bisa mengalami operasi penugasan. Nilai sari suatu variabel pointer dapat disalin ke variabel pointer yang lain.
  2. Operasi Aritmatika
    Suatu variabel pointer hanya dapat dilakukan operasi aritmatika dengan nilai integer saja. Operasi yang biasa dilakukan adalah operasi penambahan dan pengurangan. 
  3. Operasi Logika
    Operasi logika juga dapat dilakukan pada sebuah variabel pointer.


OPERASI POINTER
*  Operasi Penugasan
Suatu variable pointer seperti halnya variable yang lain, juga bisa mengalami operasi
penugasan. Nilai dari suatu variable pointer dapat disalin ke variable pointer yang lain.

//Contoh9_2
#include "iostream.h"
#include "conio.h"
void main()
{ float *x1,y, *x2;
clrscr();
y = 13.45;
x1 = &y;            /* Alamat dari y disalin ke variabel x1 */
x2 = x1;            /* Isi variabel x1 disalin ke variabel x2 */
cout<<"Nilai variabel y =  "<<y<< " ada di alamat "<< x1<<"\n";
cout<<"Nilai variabel y =  "<<y<< " ada di alamat "<< x2<<"\n";
 getch();
}

*  Operasi Aritmatika
Suatu variabel pointer hanya dapat dilakukan operasi aritmatika dengan nilai integer
saja. Operasi yang biasa dilakukan adalah operasi penambahan dan pengurangan.
Operasi penambahan dengan suatu nilai menunjukkan lokasi data berikutnya (index
selanjutnya) dalam memori. Begitu juga operasi pengurangan.

//Contoh9_3
#include <iostream.h>
#include <conio.h>
void main()
{ int nilai[3], *penunjuk;
clrscr();
nilai[0] = 125;
nilai[1] = 345;
nilai[2] = 750;
penunjuk = &nilai[0];
cout<<"Nilai "<<*penunjuk <<" ada di alamat memori " <<penunjuk<<"\n";
cout<<"Nilai "<<*(penunjuk+1) <<" ada di alamat memori " <<penunjuk+1<<"\n";
cout<<"Nilai "<<*(penunjuk+2) <<" ada di alamat memori " <<penunjuk+2<<"\n";
getch();
}

*  Operasi Logika
Suatu pointer juga dapat dikenai operasi logika.

//Contoh9_4
#include<iostream.h>
#include "conio.h"
void main()
{ int a = 100, b = 200, *pa, *pb;
clrscr();
pa = &a;
pb = &b;
cout<<"nilai pa= "<<pa<< " nilai pb= "<<pb<<"\n";
if(pa < pb)
cout<<"pa menunjuk ke memori lebih rendah dari pb\n";
if(pa == pb)
cout<<"pa menunjuk ke memori yang sama dengan pb\n";
if(pa > pb)
cout<<"pa menunjuk ke memori lebih tinggi dari pb\n";
getch();}