วันอังคารที่ 8 มีนาคม พ.ศ. 2559

บทที่ 5 คิว ( Queues )

บทที่ 5 คิว (Queue)
นิยามของคิว
     คิวมีโครงสร้างแบบเชิงเส้นเหมือนสแตก ต่างกันที่คิว มีตัวชี้ 2 ตัว คือ หัว (head)  และ หาง (tail) มีลักษณะแบบเข้าก่อนออกก่อน
การกระทำที่เกี่ยวข้องข้อมูลโครงสร้างแบบคิว
     -  การสร้างคิว (create)
     -  การนำสมาชิกข้อมูลเข้าคิว (enqueue)
     -  การนำสมาชิกออกจากคิว (dequeue)
     -  การทดสอบคิวว่าง (empty)
     -  การทดสอบคิวเต็ม (full)
     -  การทำให้คิวเป็นคิวว่าง (clear)
ลักษณะของโครงสร้างข้อมูลแบบแถวคอย
     -  คล้ายโครงสร้างขอมูลแบบสแตก
     -  ข้อมูลเข้าและออกจะทำตรงปลายคนละด้านกับสแตก
     -  ข้อมูลที่เข้ามาใหม่จะเพิ่มเข้ามาทางด้านหลัง (rear) ถ้าคิวเต็มแล้ว ยังมีการเพิ่มสมาชิกอีก จะเกิด Queue Overflow
     -  ข้อมูลที่นำออกจะอยู่ทางด้านหน้า (front) ถ้านำคิวออกจนคิวว่าง แต่ยังมีการนำออกอีก จะเกิด Queue Underflow
     -  เป็นแบบเข้าก่อนออกก่อน
การสร้างคิวด้วยอาร์เรย์ มี 4 ขั้นตอน
     1. การสร้าง
     2. การนำข้อมูลเข้า
     3. การนำข้อมูลออก
     4. การแสดงข้อมูล
     การสร้าง เป็นการแทนที่ข้อมูลคิวด้วยอาร์เรย์ เนื้อที่หน่วยความจำแบบ static นั่นคือ มีการกำหนดพื้นที่ล่วงหน้าว่ามีขนาดเท่าใด มีการกำหนดตัวชี้ 2 ตัว คือ F และ R เพื่อบอกตำแหน่งแรกสุด และ หลังสุด   
    การนำข้อมูลเข้า จะนำข้อมูลเข้าทางด้านหลัง โดยมี R เป็นตัวชี้ตรงตำแหน่งสุดท้ายไปเรื่อย ๆ จ นคิวเต็ม  
    การนำข้อมูลออก จะนำข้อมูลออกทางด้านหน้า โดยมี  F  เป็นตัวชี้ตำแหน่งที่ตัวแรก ลดถัดตามลำดับเรื่อย ๆ จนคิวว่าง
คิววงกลม (Circular Queue)   
   หลักการของคิววงกลม คือการนำหัวคิวและหางคิวมาเชื่อมต่อกันเป็นวง ทำให้สามารถเพิ่มข้อมูลไปเรื่อย ๆ โดยไม่ต้องกำหนดขนาดแบบอาร์เรย์
การประยุกต์ใช้คิว      ชนิดโครงสร้างข้อมูลแบบคิวมีความสำคัญมากในการดำเนินงานของระบบปฏิบัติการ ตัวอย่างเช่น
      - การใช้ทรัพยากร CPU จาก Server หรือ การใช้ทรัพยากร System Printer สำหรับผู้ใช้หลายคน 
      - ระบบปฏิบัติการจะใช้ชนิดข้อมูลแบบคิวในการจัดระเบียบผู้ใช้

บทที่ 4 สแตก (stack)

                                                               บทที่ 4 สแตก (stack)

โครงสร้างสแตก (Stack structure)
·         สแตก เป็นโครงสร้างข้อมูลอีกรูปแบบหนึ่งที่มีลักษณะของการจัดเก็บข้อมูลที่สามารถ จัดเก็บได้แบบทั้งเรคคอร์ด อาร์เรย์ หรือการจัดเก็บในลักษณะลิงค์ลิสต์
·         แต่ โดยรูปแบบของการทำงานนั้นจะเป็นเหมือนการจัดเก็บหรือบันทึกสมาชิกในลักษณะ ของการพักไว้
·         สแตก เป็นโครงสร้างที่ถูกออกแบบมาให้มีลักษณะเป็นเชิงเส้น สามารถที่จะทำการลบหรือเพิ่มจำนวนสมาชิกเข้ามาในโครงสร้างได้
ลักษณะ ที่สำคัญของสแตก
·         การ นำข้อมูลเข้าสู่สแตก (Insertion บางครั้งเรียกว่า Pushing)
·         การ นำข้อมูลออกจากสแตก (Deletion บางครั้งเรียกว่า Poping)
·         สามารถ กระทำได้เพียงปลายด้านเดียวของโครงสร้างเท่านั้น
·         ข้อมูล ที่เข้าไปเก็บทีหลังสุดจะถูกนำออกมาใช้ก่อน จะเรียกลักษณะแบบนี้ว่า เข้าหลักออกก่อน (Last in First out)
·         การ เข้าถึงข้อมูลในโครงสร้างจะต้องอาศัยพอยเตอร์ ซึ่งทำหน้าที่ชี้ตำแหน่งของข้อมูลตัวสุดท้ายของสแตก
 ลักษณะสำคัญของสแตก
·         โครง สร้างข้อมูลเป็นแบบเชิงเส้น (Linear structure)
·         มี โครงสร้างที่ไม่ตายตัว (dynamic sturcture)
·         นำ ข้อมูลเข้าและดึงข้อมูลออกได้ (push and pop)
·         นำ ข้อมูลเข้าและดึงข้อมูลออกแบบลำดับ
·         มี การจัดการนำเข้าและดึงข้อมูลในตำแหน่ง บนสุด
พื้น ฐานการดำเนินการกับสแตก
1. Push หรือการนำเข้าข้อมูล เป็นการดำเนินการในลักษณะของการเพิ่มข้อมูลในสแตกและต้องระวังปัญหา stack over flow คือไม่มีพื้นที่ว่างสำหรับการเพิ่มข้อมูลเข้าไปในสแตก หรือ สแตกเต็ม
2. Pop หรือการดึงข้อมูลออก  คือ การนำเอาข้อมูลออกจากสแตก ซึ่งการดำเนินการก็จะต้องดำเนินการในตำแหน่ง top หากไม่มีข้อมูลภายในสแตกแล้วยังมีการ pop จะทำให้เกิดข้อผิดพลาด stack under fow
การ ดำเนินการที่สำคัญ 6 ประการ
1.               การดำเนินการสร้างสแตก (create)
2.               การดำเนินการ push
3.               การดำเนินการ pop
4.               การดำเนินการตรวจสอบสแตกว่าง (Empty stack)
5.               การดำเนินการตรวจสอบสแตกเต็ม (Full stack)
6.               การดำเนินการกำหนดล้างสแตก (Clear stack)
การ ประยุกต์ใช้งานสแตกในการแปลงรูป นิพจน์ทางคณิตศาสตร์
รูปแบบนิพจน์ ทางคณิตศาสตร์ แบ่งเป็น 3 ประเภท คือ
1.               นิพจน์ Infix คือ นิพจน์ที่มีเครื่องหมายดำเนินการอยู่กึ่งกลางตัวถูกดำเนินการ      
2.               นิพจน์ Postfix คือ นิพจน์ที่มีเครื่องหมายดำเนินการอยู่ด้านหลังตัวถูกดำเนินการ
3.               นิพจน์ Prefix คือ นิพจน์ที่มีเครื่องหมายดำเนินการอยู่ด้านหน้าตัวถูกดำเนินการ
การ แปลงนิพจน์ Infix เป็น Postfix
สำหรับ การดำเนินการด้านการคำนวณนั้น ในระบบคอมพิวเตอร์ไม่สามารถที่จะจัดลำดับของการคำนวณในรูปแบบของ infix ได้ แต่จะแปลงเป็นนิพจน์ของ postfix ก่อน โดยลักษณะการแปลงจะใช้การเปรียบเทียบความสำคัญของตัวดำเนินการ เครื่องหมายในการคำนวณทั้ง 5 ตัว และหลักการอัลกอริทึมของการแปลงนิพจน์
ลำดับ ความสำคัญของตัวนิพจน์
1.               ^  ยกกำลัง ความสำคัญอันดับแรก
2.               *,/  คูณ,หาร รองจากยกกำลัง
3.               +,-  บวก,ลบ รองจาก ยกกำลัง คูณ หาร
4.               ( )  เครื่องหมายวงเล็บไม่ใช่ตัวดำเนินการแต่ใช้ในการกำหนดลำดับการคำนวณ
หมาย เหตุ  กรณีที่มีลำดับบอกความสำคัญเท่ากันหาไม่มีการกำหนดวงเล็บให้เทียบลำดับความ สำคัญจากซ้ายไปขวายกเว้นเลขยกกำลังความสำคัญจากขวาไปซ้าย
 
การ หาค่าผลลัพธ์จากนิพจน์ Postfix
·         ถ้าเป็นตัวถูกดำเนินการให้ push ลงสแตก
·         ถ้าเป็นตัวดำเนินการให้ pop ตัวดำเนินการออกจากสแตก 2 ตัว แล้วหาค่าผลรวมที่ดำเนินการด้วยตัวดำเนินการนั้น แล้วเก็บผลรวมลงสแตกดำเนินการกับตัวดำเนินการต่อไปจนกว่าจะหมดตัวดำเนินการ

บทที่ 3 ลิงค์ลิสต์ (Linked List)

บทที่ 3 ลิงค์ลิสต์ (Linked List)
     ลิงค์ลิสต์เป็นการจัดเก็บชุดข้อมูลเชื่อมโยงต่อเนื่องกันไปตามลำดับ ซึ่งอาจอยู่ในลักษณะแบบเชิงเส้น (Linear) หรือ ไม่เป็นเส้นตรง (nonlinear) ก็ได้
ลักษณะของลิงค์ลิสต์    1. เป็นการนำข้อมูลของแต่ละโหนดมาจัดเรียงกัน มีการเชื่อมโยงกัน
    2.ในแต่ละโหนดมี 2ฟิลด์ คือส่วนของข้อมูลและแอดเดรสของโหนดถัดไป
 
    3. ฟิลด์แอดเดรสของแต่ละโหนด เป็นตัวกำหนดลำดับ
   4. มีพอยเตอร์ชี้ไปยังโหนดแรกของลิงค์ลิสต์เสมอโหนดแรกนิยมเรียก Top,  First และ Head

    5. ฟิลด์แอดเดรสของโหนดสุดท้ายจะต่องเป็น null
    6. ลิงค์ลิตส์ที่ไม่มีโหนดอยู่ภายในเรียกว่าลิสต์ว่าง
      Dynamic  Linked  List  เป็นการใช้เนื้อที่หน่วยความจำ แบบไม่ต้องจองเนื้อที่
      Static  Linked  List  เป็นการใช้เนื้อที่หน่วยความจำ แบบอาร์เรย์แทนที่ ลิงค์ลิสต์ในหน่วยความจำ
ประเภทของลิงค์ลิสต์     ลิงค์ลิสต์เดี่ยว (Singly  Linked  List)
         -  ประกอบด้วยฟิลด์แอดเดรส 1 ฟิลด์ ชี้ไปยังโหนดถัดไป
         -  การดำเนินการเริ่มจากโหนดแรกไปโหนดสุดท้ายย้อนกลับไม่ได้
     ลิงค์ลิสต์คู่ (Doubly  Linked  List)
         - แต่ละโหนดมีฟิลด์แอดเดรส 2 ฟิลด์ ชี้ไปยังโหนดถัดไปและก่อนหน้า
         -  การดำเนินการสามารถดำเนินการไปข้างหน้าและย้อนกลับได้
การดำเนินการกับลิงค์ลิสต์    การเพิ่มโหนดให้กับลิงค์ลิสต์
    1.การเพิ่มข้อมูลที่จุดเริ่มต้นของโครงสร้างโหนดที่เพิ่มจะไปอยู่ที่ตำแหน่งแรกในลิสต์
  2. การเพิ่มข้อมูลต่อจากโหนดที่กำหนดโหนดที่เพิ่มสามารถแทรกอยู่ตรงส่วน ใดก็ได้ในลิสต์ตามที่กำหนด
    3. การเพิ่มข้อมูลที่จุดสุดท้ายของโครงสร้าง โหนดที่เพิ่มจะไปอยู่ในตำแหน่งสุดท้ายของลิสต์
    การค้นหาโหนดที่ต้องการในลิสต์
   จะใช้คำสั่ง searchnode เช่น  searchnode(chlist,B); หมายถึง ค้นหาข้อมูล B ในลิสต์ ชื่อ chlist
    การแทรกโหนดในลิสต์
    จะใช้คำสั่ง insafter เช่น insafter(num,20,25); หมายถึง เพิ่มข้อมูล 25 เข้าไปหลังโหนดที่เก็บข้อมูล 20
    การลบโหนดออกจากลิสต์
    จะใช้คำสั่ง delnode เช่น delnode(num,50); หมายถึง ลบข้อมูล 50 ออกจากลิสต์ ชื่อ num
    การท่องลิสต์
    จะใช้คำสั่ง displaynode เช่น displaynode(numlist); หมายถึง แสดงข้อมูลในลิสต์ ชื่อ numlist จะแสดงผลลัพธ์ได้หลังใช้คำสั่ง displaynode(ChL);
ลิสต์เชื่อมโยงเป็นวงกลม (Circular  List)    เป็นลิสต์ที่ไม่มีโหนดแรก และโหนดสุดท้าย
     -  สามารถเข้าถึงโหนดจากจุดใดก็ได้ในลิสต์ 
     -  ต้องมีพอยเตอร์ ชี้ที่โหนดสุดท้ายในลิสต์เพื่อบ่งบอกถึงจุดสิ้นสุด
    - การดำเนินการใด ๆ ใช้คำสั่งเดียวกับลิสต์ทางเดียว แต่ขั้นตอนในการทำงานจะต่างกัน เช่น การลบโหนดใด ๆ ออกจากลิสต์ จะต้องให้พอยเตอร์ ก่อนหน้าตัวที่จะลบ ชี้ไปโหนดที่อยู่หลังตัวที่จะลบ
ตัวอย่างโปรแกรม
การเพิ่ม Node

          #include <stdio.h>
          #include <conio.h>
          struct node
          {    
          int data;
          node *next;
          };
          node *first;
          void addnode (int i)
          {
           node *n;
           n=new node;
           n->data=i;
           if (first->next==NULL) n->next=NULL;
           else
           n->next=first->next;
           first->next=n;
           }
           void main()
           {
           clrscr();
           first=new node;
           first->data=0;
           first->next=NULL;
           addnode(5);
           addnode(9);
           addnode(4);
           addnode(7);
           addnode(3);
           node *p;
           for (p=first->next;p!=NULL;p=p->next)
                {
                      printf("data=%d\n",p->data);
                }
           getch();
           }
ผลรัน          data=3
          data=7
          data=4
          data=9
          data=5
อธิบายโปรแกรม   ลักษณะการทำงานของโปรแกรม สร้าง struct เพื่อใช้เก็บข้อมูลในโหนด และพอยเตอร์ไว้ในชุดเดียวกัน สร้างฟังก์ชั่น addnode ประกาศค่าตัวแปร i มีชนิดข้อมูลเป็นตัวเลขจำนวนเต็ม ในฟังก์ชั่นจะมีการสร้างพอยเตอร์และ โหนดใหม่ คือ n โดยใช้คำสั่ง new จองหน่วยความจำให้กับโหนด และเก็บตัวเลขที่ต้องการเอาไว้ ในที่นี้จะใช้เป็นค่าตามตัวแปร i ถ้าพอยเตอร์ frist ชี้ไปที่ NULL ก็ให้พอยเตอร์ n ชี้ไปยัง NULL แสดงว่าเป็นโหนดสุดท้าย มิฉะนั้นให้พอยเตอร์ n ชี้ไปยังโหนดที่ frist มันชี้อยู่ แล้วให้โหนด n ชี้ไปหาโหนดเดียวกับที่ first ชี้ก็เพื่อไม่ให้ list ขาดช่วง แล้ว first ก็จะมาชี้ที่ตัวใหม่นี้แทน ต่อมาในฟังก์ชั่น main ทำการสร้างโหนดแรก กำหนดค่าให้กับโหนดแรก มีค่า 0  แล้วกำหนดให้พอยเตอร์ของ frist ชี้ไปที่ NULL เพื่อให้เรารู้ว่าไม่มีสมาชิกใด ๆ ใน list  แล้วทำการเพิ่มโหนด 5, 9, 4, 7, 3 หลังจากนั้นสร้างพอยเตอร์ p ใช้คำสั่ง for วนลูป เช็คเงื่อนไข ให้ พอยเตอร์ p ชี้ไปยังตำแหน่งของโหนดที่ frist หรือโหนดล่าสุดที่เราเพิ่งเพิ่มเข้าไปนั่นเอง ถ้า p ยังไม่เป็นค่า NULL ก็ให้ p ชี้ไปยังตำแหน่งโหนดถัดไป เสร็จแสดงค่าในโหนด ตำแหน่งที่ p ชี้อยู่
การลบ Node
          #include <stdio.h>
          #include <conio.h>
          struct node
          {
           int data;
           node *next;
          };
          node *first;
          void addnode (int i)
          {  
           node *n;
           n=new node;
           n->data=i;
           if (first->next==NULL) n->next=NULL;
           else
           n->next=first->next;
           first->next=n;
           }
           void removefromfirst()
          { 
          node *p;
          p=first->next;
          first->next=p->next;
          delete p; }
          void main()
          {
          clrscr();
          first=new node;
          first->data=0;
          first->next=NULL;
          addnode(5);
          addnode(9);
          addnode(4);
          addnode(7);
          addnode(3); 
          addnode(15); 
          addnode(19); 
          addnode(56);
           node *p; printf("Current data\n");
           for (p=first->next;p!=NULL;p=p->next)
                {
                      printf("data=%d\n",p->data);
                }
          removefromfirst ();
          removefromfirst ();
          removefromfirst ();
          removefromfirst ();
          removefromfirst ();
          removefromfirst ();
          printf("\nCurrent data\n");
          for (p=first->next;p!=NULL;p=p->next)
              {
                    printf("data=%d\n",p->data);
              }
         getch();
         }
ผลรัน          Current Data
          data=56
          data=19
          data=15
          data=3
          data=7
          data=4
          data=9          
          data=5
          Current Data
          data=9
          data=5
อธิบายโปรแกรม    ลักษณะการทำงานของโปรแกรม สร้าง struct เพื่อใช้เก็บข้อมูลในโหนด และพอยเตอร์ไว้ในชุดเดียวกัน สร้างฟังก์ชั่น addnode ประกาศค่าตัวแปร i มีชนิดข้อมูลเป็นตัวเลขจำนวนเต็ม ในฟังก์ชั่น จะมีการสร้างพอยเตอร์และ โหนดใหม่ คือโหนด n โดยใช้คำสั่ง new จองหน่วยความจำให้กับโหนด และเก็บตัวเลขที่ต้องการเอาไว้ ในที่นี้จะใช้เป็นค่าตามตัวแปร i ถ้าพอยเตอร์ frist ชี้ไปที่ NULL ก็ให้พอยเตอร์ n ชี้ไปยัง NULL แสดงว่าเป็นโหนดสุดท้าย มิฉะนั้นให้พอยเตอร์ n ชี้ไปยังโหนดที่frist มันชี้อยู่ แล้วให้โหนด n ชี้ไปหาโหนดเดียวกับที่ first ชี้ก็เพื่อไม่ให้ list ขาดช่วง แล้ว first ก็จะมาชี้ที่ตัวใหม่นี้แทน  สร้างฟังก์ชั่น removefromfirst ในฟังก์ชั่นมีการสร้างพอยเตอร์ p ให้พอยเตอร์ของ frist ชี้ไปยัง โหนดที่ พอยเตอร์ p ชี้อยู่ เพื่อ ลบโหนดในตำแหน่งที่พอยเตอร์ p ชี้อยู่ ในฟังก์ชั่น main สร้างโหนดแรกและกำหนดค่าให้กับโหนดแรกมีค่า 0 แล้วกำหนดให้พอยเตอร์ของ frist ชี้ไปที่ NULL เพื่อให้เรารู้ว่าไม่มีสมาชิกใด ๆ ใน list  แล้วทำการเพิ่มโหนด 5, 9, 4, 7, 3, 15, 19, 56 สร้างพอยเตอร์ p ใช้คำสั่ง for วนลูป เช็คเงื่อนไข ให้ พอยเตอร์ p ชี้ไปยังตำแหน่งของโหนดที่ frist หรือโหนดล่าสุดที่เราเพิ่งเพิ่มเข้าไปนั่นเอง ถ้า p ยังไม่เป็นค่า NULL ก็ให้ p ชี้ไปยังตำแหน่งของโหนดถัดไป เสร็จแสดงค่าในโหนด ตำแหน่งที่ p ชี้อยู่ แล้วทำการลบโหนดจากโหนดแรก 6 โหนด ใช้คำสั่ง for วนลูป เช็คเงื่อนไข ให้ พอยเตอร์ p ชี้ไปยังตำแหน่งของโหนดที่ frist ถ้า p ยังไม่เป็นค่า NULL ก็ให้ p ชี้ไปยังตำแหน่งของโหมดถัดไป เสร็จแสดงค่าในโหนด ตำแหน่งที่ p ชี้อยู่
  1. การแทรกโหนดในลิสต์ว่าง (Insert into Empty List) 
                   กรณีนี้เป็นการแทรกโหนดเพิ่มเข้าไปในลิสต์ในขณะที่ลิสต์ว่างเปล่าหรือไม่มีข้อมูล 
ใดๆ อยู่นั่นหมายถึงเป็นการแทรกสมาชิกตัวแรกเข้าไป ซึ่งขณะนั้นเฮดพอยน์เตอร์จะมีค่าเป็น  
null เนื่องจากเป็นลิสต์ว่าง หลังจากนั้นมีลิสต์ใหม่ที่ต้องการแทรกเพิ่มเข้ามา (pNew) 
(a) Before add
                  
                                                                       (b) After add

รูป แสดงการแทรกโหนดเมื่อลิสต์ภายในว่าง

           2 การแทรกโหนดที่ตำแหน่งแรก (Insert at Beginning) 
               เป็นการแทรกโหนดเข้าไปไว้ในตำแหน่งโหนดแรก ซึ่งทำให้โหนดที่เคยอยู่ลำดับแรก 
เดิมต้องมาต่อท้ายโหนดใหม่ที่แทรกเข้าไป ขั้นตอนแรกของการแทรกข้อมูลที่โหนดแรกของลิสต์  
จะต้องทราบถึงตัวชี้ของตัว Predecessor ก่อน ซึ่งหากไม่มี หรือมีค่าเป็น nullก็หมายความว่า 
เป็นการแทรกโหนดแรกในลิสต์ว่างเปล่า
                               การแทรกโหนดที่ลำดับแรกจะมีวิธีการคือ ให้นำตัวชี้ของโหนดใหม่ชี้ไปยังโหนดแรก

           ของ ลิสต์หลังจากนั้นก็ทำการกำหนดเฮดพอยน์เตอร์ชี้ไปยังโหนดใหม่ ซึ่งเราจะรู้ตำแหน่งแอด

           เดรสของโหนดใหม่อยู่แล้วหลังจากที่ได้สร้างขึ้นมา

                                                                     (a) Before add
                   
                                                           (b) After add

                     รูป  แสดงการแทรกโหนดไว้ที่ตำแหน่งแรกของลิสต์

        3 การแทรกโหนดที่กึ่งกลางของลิสต์ (Insert in Middle) 
            การเพิ่มโหนดในส่วนกลางของลิสต์หรือการแทรกระหว่างโหนด ในขั้นตอนแรก ต้องรู้ตำ 
แหน่งโหนดก่อนหน้าเสียก่อน ซึ่งก็คือตัว Predecessor (pPre) ความสำคัญของโหนด  
Predecessor ก็คือจะมีลิงก์ที่ใช้เชื่อมโยงไปยังโหนดถัดไป 
            ในการแทรกโหนดระหว่างสองโหนด ตัวชี้หรือลิงก์ฟิลด์ของโหนดใหม่จะชี้ไปยังโหนด  
Successor ในขณะที่ตัวชี้ pPre ก็จะชี้ไปยังโหนดใหม่ 

                                                   (a) Before add
                   
                                                       (b) After add 
รูป  แสดงแทรกโหนดที่กึ่งกลางของลิสต์

          4 การแทรกโหนดที่ท้ายลิสต์ (Insert at End) 
              เมื่อมีการเพิ่มโหนดที่ส่วนท้ายของลิสต์ เราต้องการเพียงแค่ตัวชี้ของ Predecessor  
เพื่อชี้ไปยังโหนดใหม่เท่านั้น ซึ่งในที่นี้จะไม่มีโหนด Successor เนื่องจากเป็นการแทรกที่ท้าย 
ลิสต์ดังนั้นลิงก์ฟิลด์ของโหนดใหม่จึงถูกกำหนดให้เป็นค่า null

              อย่างไรก็ตาม ก็ยังมีตรรกะพิเศษในอีกรูปแบบหนึ่งเพื่อใช้กับอัลกอริทึมการแทรกโหนด
 
ที่ท้ายลิสต์ ซึ่งจัดเป็นข้อดีข้อหนึ่งของโครงสร้างลิงก์ลิสต์ โดยเราทราบอยู่แล้วว่าโหนดสุดท้ายของ 
ลิสต์จะมีตัวชี้ที่เชื่อมโยงไปที่ null นั่นหมายถึงโหนดสุดท้ายที่ไม่มีโหนดตัวถัดไปแล้วนั่นเองแต่ถ้า 
หากเรามีความต้องการใช้พอยน์เตอร์มากกว่าที่จะใช้ค่าคงที่ของ null เป็นตัวกำหนด

a) Before add

            
(b) After add

บทที่ 2 Array

                                              บทที่ 2 Array


Array โครงสร้างข้อมูลแบ่งออกเป็น 2 ประเภท คือ
1.โครงสร้างข้อมูลแบบเชิงเส้น ( Linear Lists )
เช่น อาร์เรย์( Array ), สแต็ก ( Stack ) และ คิว ( Queues )
2.โครงสร้างข้อมูลแบบไม่เป็นเชิงเส้น ( Non-Linear Lists )        
เช่น ทรี ( Trees ) และกราฟ ( Graphs )
โครงสร้างข้อมูลแบบอาร์เรย์
            อาร์เรย์ ( Array ) หรือแถวลำดับ คือการรวมกลุ่มของตัวแปรที่สามารถใช้ตัวแปรชื่อเดียวแทนข้อมูลสมาชิกได้หลายๆตัว ใช้เลขดรรชนี ( index ) หรือ ( Subscript ) เป็นตัวอ้างอิงตำแหน่งสมาชิกบนแถวลำดับ
คุณสมบัติสำคัญของอาร์เรย์

1.อาร์เรย์เป็นตัวแทนของกลุ่มที่มีความสัมพันธ์กัน

2.มีชนิดข้อมูลเหมือนกันทั้งหมด

3.อาร์เรย์มีขนาดคงที่

4.ผู้ใช้สามารถอ้างอิงเพื่อเข้าถึงข้อมูลที่ต้องการได้ทันที

การอ้างอิงตำแหน่งสมาชิกในอาร์เรย์
ต้องเริ่มต้นด้วยชื่ออาร์เรย์และตามด้วยเลขลำดับกำกับไว้ 
ด้วย สามารถเรียกได้หลายชื่อด้วยกัน เช่น เลขลำดับ เรียกอีกชื่อ ซัป
สคริปต์ หรือเลขดรรชนี
ขอบเขตของอาร์เรย์ (Bounds)         เลขดรรชนีในอาร์เรย์ประกอบด้วยช่วงขอบเขตของค่าซึ่งประกอบด้วยขอบเขตล่างสุดและขอบเขตบนสุด
การคำนวณหาจำนวนสมาชิก                                            
โดยที่  U  = ขอบเขตบนสุด  , L = ขอบเขตล่างสุด
อาร์เรย์ 1 มิติ  ใช้สูตร         U – L + 1                                  
อาร์เรย์ 2 มิติ  ใช้สูตร  ( U1 – L1 + 1) * ( U2 – L2 + 1)
การจัดเก็บอาร์เรย์ในหน่วยความจำ
-อาร์เรย์จัดเก็บอยู่ในหน่วยความจำคอมพิวเตอร์จะมีลักษณะเป็นลำดับต่อเนื่องกัน
-ใช้เนื้อที่ในการจัดเก็บข้อมูลสมาชิกของแต่ละตัวในขนาดเท่าๆกัน
-สมาชิกทุกตัวในต้องเป็นข้อมูลชนิดเดียวกัน
รูปแบบทั่วไปของโครงสร้างข้อมูลอาร์เรย์
 อาร์เรย์ 1 มิติ ใช้สูตร ArrayName [ L:U ]
 a[1:10] = a[10] 
  
อาร์เรย์ 2 มิติ ใช้สูตร ArrayName [ L1:U1,L2:U2 ]
          
 a[4,5] = a[0:3,0:4] 
อาร์เรย์ 3 มิติ ใช้สูตร ArrayName [ L1:U1,L2:U,L3:U3 ]
a[6,5,4] = a[0:5,0:4,0:3] 
การคำนวณหาตำแหน่งแอดเดรสในหน่วยความจำอาร์เรย์ 1 มิติ
ใช้สูตร LOC(a[i]) = B + w(i – L) 
โดยที่                                                                                
LOC(a[i]) คือ ตำแหน่งแอดเดรสที่เก็บ a[i] ในหน่วยความจำ                    
B คือ แอดเดรสเริ่มต้นของ a                                              
w  คือ ขนาดของข้อมูลในการจัดเก็บ                                 
 i คือ ตำแหน่งของสมาชิกในอาร์เรย์                                  
 L คือ ขอบเขตล่างสุด                                                          
 
ตัวอย่าง
อยากทราบอาร์เรย์ a[10] (ภาษา C ) ถูกจัดเก็บในหน่วยความจพเดรสใด กำหนดให้ : 
 แอดเดรสเริ่มต้น = 1000      w =  1 ไบต์
LOC(a[i]) = B + w(i – L)                
                  = 1000 + 1(10-0)
                  = 1000 + 10
                  = 1010
อาร์เรย์ 2 มิติ                                                                        การจัดเก็บด้วยการเรียงคอลัมน์เป็นหลัก 
ใช้สูตร      LOC(a[i]) = B + w[C(i – L1) + ( j – L2)] 
โดยที่ C  คือตำแหน่งคอลัมน์ของแถวลำดับ ( R*C )          
ตัวอย่าง  ต้องการทราบตำแหน่งที่เก็บข้อมูลอาร์เรย์ K แถวที่ 2 คอลัมน์ 1 กำหนด B = 500, w = 4 ( ภาษา C )
LOC(K[i,j]     = B + w[C(i – L1) + ( j – L2)]
LOC(K[2,1])  = 500 + 4[3(2– 0) + ( 1 – 0)]
                        = 500 + 4[6 +1]
                        = 500 +28
                        = 528
อาร์เรย์ 3 มิติ                                                                          
การจัดเก็บด้วยการเรียงแถวเป็นหลัก       ใช้สูตร
 LOC(s[i,j,k])  = B + [ w * R * C( i - L1)                
                                     + [w * C( j – L2 )] + [w(k-L3)]
ตัวอย่าง      
ต้องการทราบตำแหน่งที่เก็บข้อมูลอาร์เรย์ S ชั้นที่ 0 แถวที่ 3 คอลัมน์ 4 กำหนดให้ B = 500, w =4 (ภาษา C S[3][4][5] )
LOC(s[i,j,k])  = B + [ w * R * C( i - L1)                
                               + [w * C( j – L2 )] + [w(k-L3)]
LOC(s[0,3,4])  = 500 + [ 4 * 4 * 5( 0 - 0)                
                                     + [4 * 5( 3– 0 )] + [4(4-0)]
                           = 500 + 0 + 60 + 16
                          = 576
อาร์เรย์ 3 มิติ 
-การนำเอาอาร์เรย์ 2 มิติ มาเรียงซ้อนกันหลายๆ ชั้น
-มีแถว (row) และคอลัมน์ (column) และความลึก(deap)
                                      
การจัดเก็บด้วยการเรียงคอลัมน์เป็นหลัก      
ใช้สูตร
LOC( S[i,j,k]) = B + [w * K * R * C(j – L2) ]
                                + [ w * K * R(i – L)]  + [k – L3]
การคำนวณหาตำแหน่งแอดแดรสในหน่วยความจำของอาร์เรย์ 3 มิติ
สามารสจัดเก็บได้ 2 วิธี
1. การจัดเก็บด้วยการเรียงแถวเป็นหลัก (Row Major Order)
2. การจัดเก็บด้วยการเรียงคอลัมน์เป็นหลัก (Column Major Order)

รูปที่1  แสดงอาร์เรย์  number ที่จัดเก็บอยู่ภายในหน่วยความจำคอมพิวเตอร์

                  อาร์เรย์สองมิติ (Two  Dimension  Array)                                      อาร์เรย์สองมิติจะมีรูปแบบตารางที่ประกอบด้วยแถว (Row) และคอลัมม์ (Column) การอ้าองอิงอาร์เรย์สองมิติจึงต้องระบุบแนวแถวและคอลัมม์  สำหรับรูปแบบทั่วไปของโครงสร้างข้อมูลอาร์เรย์สองมิติ  คือ                                                   ArrayName [L1 : U1 , L2 : U2]                                       โดยที่  ArrayName  คือชื่อของอาร์เรย์                    L1   คือขอบเขตล่างสุด  (Lower Bound)  ของแถว                   U1  คือขอบเขตบนสุด  (Upper Bound)   ของแถว                   L2   คือขอบเขตล่างสุด  (Lower Bound)  ของคอลัมน์                  U2  คือขอบเขตบนสุด  (Upper Bound)   ของคอลัมน์                 โดยสมมติว่าได้มีการกำหนดให้ K[4,3] หรือ K[0:3,0:2] ด้วยภาษา C ดังนี้                  int K[4] [3];                ซึ่งแสดงได้ดังรูป