Thank you to @Joseinnewworld who just bought 6 of our #NFTs, your appreciation means a lot to us as builders. You are amazing 🤩 #eCash $XEC #nftcollector #NFTDrop #BlockchainSimplicity #NFT #Bitcoin #NFT4season #NFTMint pic.twitter.com/3sWAlhxPpv
— Gaexe (@gaexe_) January 21, 2025
One form of data structure that contains a collection of data arranged sequentially, connected to each other, dynamically is a linked list. A linked list is a node that is linked to other nodes in a certain order. A node can take the form of a structure or class. Nodes must have one or more structural elements or classes that contain data.
Image of a node:
1]. The first part, called the information field, contains the information to be stored and processed.
2]. The second part, called the link field, contains the address of the next node.
In the above image, the start pointer points to the first node of the list. The connecting field (pointer) of a node that does not point to another node is called an empty pointer, whose value is declared as null (null is a standard word meaning that the pointer is 0 or a negative number). So we can see that with just a Start pointer, we can read all the information stored in the list.
In theory, a linked list is a number of nodes connected linearly with the help of pointers. It is said to be single linked if there is only one pointer connecting each node. Single means that the pointer field is only one and in one direction.
A linked list is the most basic data structure. Linked lists consist of a number of elements grouped, or linked, together in a specific series. Linked lists are useful in maintaining collections of data, which are similar to the frequently used arrays. However, linked lists provide important advantages over arrays in many ways. In detail, linked lists are more efficient in carrying out insertions and deletions.
Linked lists also use dynamic storage allocation, which is storage allocated at runtime. Since in many applications, the size of the data is not known at compile time, this can be a good attribute. Each node will be a struct and have one field of the same struct type, which acts as a pointer. In connecting each node, we can use the first-create-first-access or first-create-last-access method. What is different from the previous struct declaration is a field called next, which is of type struct node. This can be confusing at first glance. However, one thing is clear, this next variable will connect us to the node next to us, which is also of type struct node. This is why next must be of type struct node.
Node Declaration
struct node {
char nama[20];
int umur;
float tinggi;
node *next; // Pointer menyambung ke node selanjutnya
};
You can find a more detailed discussion of the complete program sections below here:
- How to Add a Knot
- How to Delete a Knot
- How to Display Nodes (you can see it here).
3. Displaying Node List
Before displaying a linked list, we need to test whether the list is empty or not. If the list is empty, we display a message that the List is empty. If the list is not empty, then we read the list from the starting position to the last node.
node *temp;
temp = awal_ptr;
cout << endl;
if (temp == NULL)
cout << "List kosong!" << endl;
else
{
while (temp != NULL)
{
// Menampilkan isi
cout << "Nama : " << temp->nama << " ";
cout << "Umur : " << temp->umur << " ";
cout << "Tinggi : " << temp->tinggi;
if (temp == posisi)
cout << " <-- Posisi node";
cout << endl;
temp = temp->next;
}
cout << "Akhir list!" << endl;
}
Complete Program 1
#include <iostream.h>
struct node
{
char nama[20];
int umur;
float tinggi;
node *next;
};
node *awal_ptr=NULL;
node *posisi;
int pilih;
void tambah_simpul_akhir()
{
node *temp, *temp2; //simpul sementara
//isi data
temp=new node;
cout<<"Nama : ";cin>>temp->nama;
cout<<"Umur : ";cin>>temp->umur;
cout<<"Tinggi : ";cin>>temp->tinggi;
temp->next=NULL;
//inisialisasi pointer ketika kosong
if(awal_ptr==NULL)
{
awal_ptr=temp;
posisi=awal_ptr;
}
else
{
temp2=awal_ptr;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next=temp;
}
}
void tampil_senarai()
{
node *temp;
temp = awal_ptr;
if(temp == NULL)
cout<<"List kosong"<<endl;
else
{
cout<<endl<<endl;
while(temp != NULL)
{
cout<<"Nama : "<<temp->nama<<" ";
cout<<"Umur : "<<temp->umur<<" ";
cout<<"Tinggi : "<<temp->tinggi;
if (temp == posisi)
cout<<" << posisi simpul";
cout<<endl;
temp=temp->next;
}
cout<<"Akhir list"<<endl;
}
}
void hapus_simpul_akhir()
{
node *temp1, *temp2;
if (awal_ptr == NULL)
cout << "List kosong!" << endl;
else
{
temp1 = awal_ptr;
if (temp1->next == NULL)
{
delete temp1;
awal_ptr = NULL;
}
else
{
while (temp1->next != NULL)
{
temp2 = temp1;
temp1 = temp1->next;
}
delete temp1;
temp2->next = NULL;
}
}
}
void hapus_simpul_awal()
{
node *temp;
temp = awal_ptr;
awal_ptr = awal_ptr->next;
delete temp;
}
void main()
{
awal_ptr=NULL;
do
{
tampil_senarai();
cout<<"Menu Pilihan"<<endl;
cout<<"0. Keluar program"<<endl;
cout<<"1. Tambah simpul akhir"<<endl;
cout<<"2. Hapus simpul akhir"<<endl;
cout<<"3. Hapus simpul awal"<<endl;
cout<<"Pilihan >> ";cin>>pilih;
switch(pilih)
{
case 1: tambah_simpul_akhir();break;
case 2: hapus_simpul_akhir();break;
case 3: hapus_simpul_awal();break;
}
}while(pilih !=0);
}
Complete Program 2
#include <iostream.h>
#include <conio.h>
struct node
{ char nama[20];
int umur;
float tinggi;
node *next;
};
node *awal_ptr = NULL;
node *posisi; //digunakan untuk membaca sepanjang list
int option = 0;
void tambah_awal_list()
{
node *baru;
baru = new node;
cout << "Masukkan Nama : ";
cin >> baru->nama;
cout << "Masukkan Umur : ";
cin >> baru->umur;
cout << "Masukkan tingggi : ";
cin >> baru->tinggi;
baru->next = NULL;
if(awal_ptr == NULL)
{
awal_ptr=baru;
awal_ptr->next = NULL;
}
else
{
baru->next = awal_ptr;
awal_ptr = baru;
}
}
void menambah_node_di_akhir()
{ node *temp, *temp2; // Temporary pointers
// menciptakan node baru
temp = new node;
cout << "Masukkan Nama : ";
cin >> temp->nama;
cout << "Masukkan Umur : ";
cin >> temp->umur;
cout << "Masukkan tingggi : ";
cin >> temp->tinggi;
temp->next = NULL;
// Set up link pada node
if (awal_ptr == NULL)
{ awal_ptr = temp;
posisi = awal_ptr;
}
else
{ temp2 = awal_ptr;
// node tidak NULL -- list tidak kosong
while (temp2->next != NULL)
{ temp2 = temp2->next;
// Memindahkan pada next link dalam rantai
}
temp2->next = temp;
}
}
void display_list()
{ node *temp;
temp = awal_ptr;
cout << endl;
if (temp == NULL)
cout << "List kosong!" << endl;
else
{ while (temp != NULL)
{ // Menampilkan detail data
cout << "nama : " << temp->nama << " ";
cout << "umur : " << temp->umur << " ";
cout << "tinggi : " << temp->tinggi;
if (temp == posisi)
cout << " <<<< posisi node";
cout << endl;
temp = temp->next;
}
cout << "Akhir list!" << endl;
}
}
void hapus_awal_node()
{ node *temp;
temp = awal_ptr;
awal_ptr = awal_ptr->next;
delete temp;
}
void hapus_akhir_node()
{ node *temp1, *temp2;
if (awal_ptr == NULL)
cout << "List kosong!" << endl;
else
{ temp1 = awal_ptr;
if (temp1->next == NULL)
{ delete temp1;
awal_ptr = NULL;
}
else
{ while (temp1->next != NULL)
{ temp2 = temp1;
temp1 = temp1->next;
}
delete temp1;
temp2->next = NULL;
}
}
}
void pindah_posisi_sebelumnya()
{ if (posisi->next == NULL)
cout << "Kamu berada pada akhir list." << endl;
else
posisi = posisi->next;
}
void pindah_posisi_berikutnya()
{ if (posisi == awal_ptr)
cout << "Kamu berada pada awal list" << endl;
else
{ node *previous; // deklarasi pointer
previous = awal_ptr;
while (previous->next != posisi)
{ previous = previous->next;
}
posisi = previous;
}
}
void tambah_tengah_list()
{
node *baru, *bantu;
int posisi_sisip;
if(awal_ptr != NULL)
{
cout<<"Akan disisip setelah Data Ke ? : "; cin>>posisi_sisip;
bantu=awal_ptr;
baru =new node;
for(int i=1;i<posisi_sisip-1;i++)
{
if(bantu->next != NULL)
bantu=bantu->next;
else
break;
}
cout << "Masukkan Nama : ";
cin >> baru->nama;
cout << "Masukkan Umur : ";
cin >> baru->umur;
cout << "Masukkan tingggi : ";
cin >> baru->tinggi;
baru->next=bantu->next;
bantu->next=baru;
}
else
{ cout<<"Belum ada data !! silahkan isi data dulu....";
getch();}
}
void Hapus_tengah_list()
{
int banyakdata,posisi_hapus,poshapus;
node *hapus, *bantu;
if(awal_ptr != NULL)
{
cout<<" Akan dihapus pada data ke : "; cin>>posisi_hapus;
banyakdata=1;
bantu=awal_ptr;
while(bantu->next != NULL)
{
bantu=bantu->next;
banyakdata++;
}
if((posisi_hapus<1)||(posisi_hapus>banyakdata))
{
cout<<"Belum ada data !! masukkan Data dula aja...\n";
}
else
{
bantu=awal_ptr;
poshapus=1;
while(poshapus<(posisi_hapus-1))
{
bantu=bantu->next;
poshapus++;
}
hapus=bantu->next;
bantu->next=hapus->next;
delete hapus;
}
}
else cout<<"Data Masih kosong, tidak bisa hapus data dari tengah! ";
getch();
}
int main()
{ awal_ptr = NULL;
do
{
clrscr();
display_list();
cout << endl;
cout << "MENU PILIHAN : " << endl;
cout << "0. Keluar program." << endl;
cout << "1. Tambah awal list." << endl;
cout << "2. Tambah akhir list." << endl;
cout << "3. Tambah tengah list."<< endl;
cout << "4. Hapus awal list." << endl;
cout << "5. Hapus akhir list." << endl;
cout << "6. Hapus tengah list." << endl;
cout << "7. Pindah posisi pointer ke berikutnya." << endl;
cout << "8. Pindah posisi pointer ke sebelumnya." << endl;
cout << endl << " Pilihan >> ";
cin >> option;
switch (option)
{
case 1 : tambah_awal_list();break;
case 2 : menambah_node_di_akhir(); break;
case 3 : tambah_tengah_list();break;
case 4 : hapus_awal_node(); break;
case 5 : hapus_akhir_node(); break;
case 6 : Hapus_tengah_list();break;
case 7 : pindah_posisi_sebelumnya(); break;
case 8 : pindah_posisi_berikutnya();
}
}
while (option != 0);
}
Source
Data Structure Course. STMIK EL Rahma Yogyakarta.
Compiled by Eko Riswanto
C++ Linked List / Array / Chained List Example
Arrays or in other terms are often called arrays or some also call them indexed variables, because they are composed of several elements, each of which has an index and for arrays the index starts from 0, as a basis we will start from a one-dimensional array, here we will try to display the contents of each array element by inputting its index.
Program:
#include <iostream.h>
#include <conio.h>
//bundet.com
void main(){
int a[1];
int i,j;
cout<<"Jumlah elemen yang di inginkan : ";
cin>>j;
for(int k=0; k<j; k++){
cout<<"indek ke-"<<k<<":";
cin>>i;
a[k]=i;
}
cout<<endl;
cout<<"isi larik adalah : ";
for(int k=0; k<j; k++){
cout<<a[k]<<"-";
}
getch();
}
Output:
Hope this is useful and happy learning!
Understanding Double Linked List
Elements are connected by two pointers in one element. This structure causes the list to traverse both forward and backward. Each element in a double linked list consists of three parts, in addition to the data and the next pointer, each element is equipped with a prev pointer that points to the previous element. A double linked list is formed by arranging a number of elements so that the next pointer points to the element that follows it and the prev pointer points to the element that precedes it. To indicate the head of a double linked list, the prev pointer of the first element points to NULL. To indicate the tail of the double linked list, the next pointer of the last element points to NULL. The arrangement of elements that are connected in the form of a double linked list can be seen in the Figure below.
Figure 1. A node using a double linked list
To traverse back through a double linked list, we use the prev pointer from the next element in the tail to head direction. A double linked list has more flexibility than a single linked list in moving through the list. This form is very useful when you want to place an element in the list and can choose more wisely how to move it. For example, one of the flexibilities of a double linked list is in terms of moving elements than using a single linked list.
Definition of node
struct node
{ char nama[20];
int umur;
float tinggi;
node *prev;
node *next;
};
After the node is created, create a new variable of type pointer from the node that serves as the head and tail of the linked list. The head always points to the first node, while the tail always points to the last node.
node *head=NULL, *tail=NULL;
You can read a more detailed review of the sections of the complete program below here:
- Adding a Double Linked List Node
- Deleting Double Linked List Nodes
Complete Program
#include <iostream.h>
#include <conio.h>
#include <stdio.h>
int pil;
void pilih();
void buat_baru();
void tambah_belakang();
void tambah_depan();
void hapus_belakang();
void hapus_depan();
void tampil();
struct node
{
char nama [20];
int umur;
float tinggi;
node *prev, *next;
};
node *baru, *head=NULL, *tail=NULL,*hapus,*bantu;
void main()
{
do
{
clrscr();
cout<<"MENU DOUBLE LINKEDLIST"<<endl;
cout<<"1. Tambah Depan"<<endl;
cout<<"2. Tambah Belakang"<<endl;
cout<<"3. Hapus Depan"<<endl;
cout<<"4. Hapus Belakang"<<endl;
cout<<"5. Tampilkan"<<endl;
cout<<"6. Selesai"<<endl;
cout<<"Pilihan Anda : ";
cin>>pil;
pilih();
} while(pil!=6);
}
void pilih()
{
if(pil==1)
tambah_depan();
else if(pil==2)
tambah_belakang();
else if(pil==3)
hapus_depan();
else if(pil==4)
hapus_belakang();
else if(pil==5)
tampil();
else
cout<<"selesai";
}
void buat_baru()
{
baru = new(node);
cout<<"input nama : ";cin>>baru->nama;
cout<<"input umur : ";cin>>baru->umur;
cout<<"input tinggi : ";cin>>baru->tinggi;
baru->prev=NULL;
baru->next=NULL;
}
void tambah_belakang()
{
buat_baru();
if(head==NULL)
{
head=baru;
tail=baru;
}
else
{
tail->next=baru;
baru->prev=tail;
tail=baru;
}
cout<<endl<<endl;
tampil();
}
void tambah_depan()
{
buat_baru();
if(head==NULL)
{
head=baru;
tail=baru;
}
else
{
baru->next=head;
head->prev=baru;
head=baru;
}
cout<<endl<<endl;
tampil();
}
void hapus_depan()
{
if (head==NULL)
cout<<"Kosong";
else if (head->next==NULL)
{
hapus=head;
head=NULL;
tail=NULL;
delete hapus;
}
else
{
hapus=head;
head=hapus->next;
head->prev=NULL;
delete hapus;
}
cout<<endl<<endl;
tampil();
}
void hapus_belakang()
{
if (head==NULL)
cout<<"Kosong";
else if (head->next==NULL)
{
hapus=head;
head=NULL;
tail=NULL;
delete hapus;
}
else
{
hapus=tail;
tail=hapus->prev;
tail->next=NULL;
delete hapus;
}
cout<<endl<<endl;
tampil();
}
void tampil()
{
if (head==NULL)
cout<<"Kosong";
else
{
bantu=head;
while(bantu!=NULL)
{
cout<<" nama : "<<bantu->nama;
cout<<" umur : "<<bantu->umur;
cout<<" tinggi : "<<bantu->tinggi<<endl;
bantu=bantu->next;
}
}
getch();
}
Source
Data Structure Course. STMIK EL Rahma Yogyakarta.
Compiled by Eko Riswanto
Adding a Double Linked List Node (Create Node)
To create a new node, the new keyword is used. This command is used to prepare a node with its memory allocation. Next, the information field on the node is filled with certain data. Finally, the prev and next pointers are filled with NULL.
Function to create new node
void buat_baru()
{
baru = new(node);
cout<<"input nama : ";cin>>baru->nama;
cout<<"input umur : ";cin>>baru->umur;
cout<<"input tinggi : ";cin>>baru->tinggi;
baru->prev=NULL;
baru->next=NULL;
}
1. Adding a Knot at the Beginning
Addition of new nodes that will be placed at the front node, it should be noted that the first time (data is still empty), then when adding data is done, the head/tail is shown to the new node. While if it is not empty, the data will be added in front of the head, then the new node will change to the head.
The function adds a node at the beginning
void tambah_depan()
{
buat_baru();
if(head==NULL)
{
head=baru;
tail=baru;
}
else
{
baru->next=head;
head->prev=baru;
head=baru;
}
cout<<endl<<endl;
tampil();
}
2. Add a Knot at the Back
The addition of a node at the back will always be associated with the tail and then the new node will become the tail.
The function of adding a node at the back
void tambah_belakang()
{
buat_baru();
if(head==NULL)
{
head=baru;
tail=baru;
}
else
{
tail->next=baru;
baru->prev=tail;
tail=baru;
}
cout<<endl<<endl;
tampil();
}
Source
Data Structure Course. STMIK EL Rahma Yogyakarta.
Compiled by Eko Riswanto
Deleting Double Linked List Nodes (Delete Node)
1. Remove the Node at the Beginning
Deleting a node should not be done if the node is being pointed to by a pointer, then another pointer must be used to point to the node to be deleted, for example the delete pointer. Then the head must be pointed to the next node first so that the list does not break, so that the node after the old head will become the new head. After that, delete the delete pointer using the delete command. If the head is still NULL then it means the data is still empty!
Function to delete the front node
void hapus_depan()
{
if (head==NULL)
cout<<"Kosong";
else if (head->next==NULL)
{
hapus=head;
head=NULL;
tail=NULL;
delete hapus;
}
else
{
hapus=head;
head=hapus->next;
head->prev=NULL;
delete hapus;
}
cout<<endl<<endl;
tampil();
}
2. Removing the Knot at the Back
Deleting a node behind requires one helper pointer, for example the delete pointer, no need to loop to find the last node as in a single linked list. The delete pointer only needs to point to the tail pointer. Before deleting a node, the tail must be moved to the previous node. Next, the next pointer from the tail is given a NULL value. Then the last step is to delete the delete node
Function to delete the node behind
void hapus_belakang()
{
if (head==NULL)
cout<<"Kosong";
else if (head->next==NULL)
{
hapus=head;
head=NULL;
tail=NULL;
delete hapus;
}
else
{
hapus=tail;
tail=hapus->prev;
tail->next=NULL;
delete hapus;
}
cout<<endl<<endl;
tampil();
}
Source
Data Structure Course. STMIK EL Rahma Yogyakarta.
Compiled by Eko Riswanto
How to Add a Node (Create Node)
1. Add a Knot in the Front
It is adding a new node that is inserted at the beginning of the list. The process of adding a node at the beginning of the list is illustrated as follows:
1]. The list is still empty then the initial_ptr value is NULL (initial_ptr=NULL)
2]. Enter a new node, for example data A.
3]. Add a node at the beginning of node A, for example node B.
New -> next is filled with the address where data node A is located, then awal_ptr is pointed to the new node that was created.
Program:
if(awal_ptr == NULL)
{
awal_ptr=baru;
awal_ptr->next = NULL;
}
else
{
baru->next = awal_ptr;
awal_ptr = baru;
}
2. Add a Knot in the Middle
The process of adding in the middle means the process of inserting data at a certain position. Therefore, the insertion position is very necessary. There are several conditions that must be considered when you want to insert data, namely the condition when the linked list is still empty, and when the linked list already has data.
The process of adding data when the linked list already has data. There are 3 conditions that occur when the insertion process is carried out on a linked list that already has data, namely:
- The insertion position is outside the range of the linked list (position less than 1 or exceeds the amount of data in the linked list). In this process, if the insertion position is less than 1, the process carried out is the process of adding data at the beginning, and if the position is outside (>) of the amount of data, the process carried out is the process of adding data at the end.
- Insertion position within the linked list range. For example, if you want to insert data at position 3 (insert_position=3).
The next step is to find the position of the element before the insert position and then save it in a variable with the auxiliary name.
Then connect the next field of New to the next position of auxiliary.
Then move the next field from the help to the new data position.
Program:
if(awal_ptr != NULL)
{
cout<<"Akan disisip setelah Data Ke ? : "; cin>>posisi_sisip;
bantu=awal_ptr;
baru =new node;
for(int i=1;i<posisi_sisip-1;i++)
{
if(bantu->next != NULL)
bantu=bantu->next;
else
break;
}
cout << "Masukkan Nama : "; cin >> baru->nama;
cout << "Masukkan Umur : "; cin >> baru->umur;
cout << "Masukkan tingggi : "; cin >> baru->tinggi;
baru->next=bantu->next;
bantu->next=baru;
}
else
{ cout<<"Belum ada data !! silahkan isi data dulu....";
getch();}
}
3. Add a Knot at the Back
Now we will learn how to add a new node to the linked list. We assume that the new node to be added always occupies the position after the last known position of the linked list. To explain this operation, let's use pointer and node declarations as below:
struct node {
char nama[20];
int umur;
float tinggi;
node *next;
};
Suppose the new node that is formed is named temp. To add a new node, we need to test whether the Linked list is still empty or not. An empty Linked list is marked with awal_ptr having a value of NULL. If it is not empty, then the existing list is read from the initial position to the last, for example by using the temp2 pointer. The last node is marked with the connecting field of temp2 having a value of NULL. If it is already at the last node, we show the connecting field of temp2 with temp.
The complete program adds a node to the end of the list as follows:
node *temp, *temp2; // pointer sementara
// Isi data
temp = new node; //menciptakan node baru
cout << "Nama : ";cin >> temp->nama;
cout << "Umur : ";cin >> temp->umur;
cout << "Tinggi : ";cin >> temp->tinggi;
temp->next = NULL;
// Inisialisasi pointer ketika masih kosong
if (awal_ptr == NULL)
{
awal_ptr = temp;
posisi = awal_ptr;
}
else
{
temp2 = awal_ptr;
// list tidak kosong
while (temp2->next != NULL)
{
temp2 = temp2->next;
// pindah ke link berikutnya
}
temp2->next = temp;
}
Source
Data Structure Course. STMIK EL Rahma Yogyakarta.
Compiled by Eko Riswanto
How to Delete Node
1. Remove the Node at the Beginning
Deleting a node at the beginning is done by containing the initial node in the temp pointer, then pointing awal_ptr to the next node. Then the node contained in the temp pointer is deleted.
node *temp;
temp = awal_ptr;
awal_ptr = awal_ptr->next;
delete temp;
2. Removing the Knot in the Middle
Deleting the middle of a node is removing the node from the linked list.
Suppose we want to delete the node at position 3.
Place the auxiliary pointer at the position before the node to be deleted.
Place the delete pointer according to the next field in the helper.
Connect the next field on help with the next field on delete.
The last step is to delete the delete node.
Program:
if(awal_ptr != NULL)
{
cout<<" Akan dihapus pada data ke : "; cin>>posisi_hapus;
banyakdata=1;
bantu=awal_ptr;
while(bantu->next != NULL)
{
bantu=bantu->next;
banyakdata++;
}
if((posisi_hapus<1)||(posisi_hapus>banyakdata))
{
cout<<"Belum ada data !! masukkan Data dula aja...\n";
}
else
{
bantu=awal_ptr;
poshapus=1;
while(poshapus<(posisi_hapus-1))
{
bantu=bantu->next;
poshapus++;
}
hapus=bantu->next;
bantu->next=hapus->next;
delete hapus;
}
}
else cout<<"Data Masih kosong, tidak bisa hapus data dari tengah! ";
getch();
}
3. Remove the node at the end
To delete the node at the end we need to test whether the list is still empty or not, if it is empty, display a message that the list is still empty. If it is not empty, it is necessary to test whether the number of nodes in the list is only one which is marked with a connecting field that is null. If there is more than one node then read all the nodes until the last node, namely the connecting field is null.
node *temp1, *temp2;
if (awal_ptr == NULL)
cout << "List kosong!" << endl;
else
{
temp1 = awal_ptr;
if (temp1->next == NULL)
{
delete temp1;
awal_ptr = NULL;
}
else
{
while (temp1->next != NULL)
{
temp2 = temp1;
temp1 = temp1->next;
}
delete temp1;
temp2->next = NULL;
}
}
Source
Data Structure Course. STMIK EL Rahma Yogyakarta.
Compiled by Eko Riswanto