การเรียงลำดับการแทรก: อัลกอริทึมด้วย C, C++, Java, Python ตัวอย่าง
การเรียงลำดับการแทรกคืออะไร?
การเรียงลำดับแบบแทรกเป็นหนึ่งในอัลกอริทึมการเรียงลำดับแบบเปรียบเทียบที่ใช้ในการเรียงลำดับองค์ประกอบด้วยการทำซ้ำกับองค์ประกอบหนึ่งครั้งละหนึ่งองค์ประกอบและวางองค์ประกอบไว้ในตำแหน่งที่ถูกต้อง
แต่ละองค์ประกอบจะถูกแทรกตามลำดับในรายการที่เรียงลำดับแล้ว ขนาดของรายการที่เรียงลำดับแล้วในตอนแรกคือขนาดเดียว อัลกอริธึมการเรียงลำดับการแทรกช่วยให้แน่ใจว่าองค์ประกอบ k แรกจะถูกจัดเรียงหลังจากการวนซ้ำที่ k
ลักษณะของอัลกอริทึมการเรียงลำดับการแทรก
อัลกอริทึมสำหรับการเรียงลำดับแบบแทรกมีคุณลักษณะสำคัญดังต่อไปนี้:
- เป็นเทคนิคการเรียงลำดับที่มีความเสถียร จึงไม่เปลี่ยนลำดับสัมพัทธ์ขององค์ประกอบที่เท่ากัน
- มีประสิทธิภาพสำหรับชุดข้อมูลขนาดเล็ก แต่ไม่มีประสิทธิภาพสำหรับรายการขนาดใหญ่
- การเรียงลำดับการแทรกเป็นแบบปรับเปลี่ยนได้ ซึ่งจะช่วยลดจำนวนขั้นตอนทั้งหมดหากมีการเรียงลำดับเพียงบางส่วน แถว ไว้เป็นข้อมูลเข้าเพื่อให้มีประสิทธิภาพ
แทรกอย่างไร Operaทำงานเหรอ?
ในอัลกอริทึมการเรียงลำดับแบบแทรก การดำเนินการแทรกใช้เพื่อเรียงลำดับองค์ประกอบที่ไม่ได้เรียงลำดับ การดำเนินการนี้ช่วยในการแทรกองค์ประกอบใหม่ลงในรายการที่เรียงลำดับแล้ว
รหัสเทียมของการดำเนินการแทรก:
พิจารณารายการ A ขององค์ประกอบ N
A[N-1] is the element to be inserted in the sorted sublist A[0..N-2]. For i = N-1 to 1: if A[i] < A[i-1], then swap A[i] and A[i-1] else Stop
ในตัวอย่างข้างต้น องค์ประกอบใหม่ 6 จะถูกแทรกลงในรายการที่เรียงลำดับแล้ว
ขั้นตอน 1) เมื่อเปรียบเทียบกับองค์ประกอบที่อยู่ติดกันทางซ้ายของ A[5], 9 > 6 เราจะสลับตำแหน่งที่ 9 และ 6 ตอนนี้องค์ประกอบที่ 6 ถูกย้ายไปที่ A[4]
ขั้นตอน 2) ตอนนี้ เราเปรียบเทียบ A[4] และ A[3] และเราพบว่า A[3] > A[4] เราสลับตำแหน่ง 6 และ 8 อีกครั้ง
ขั้นตอน 3) ตอนนี้เปรียบเทียบ A[3] และ A[2] โดยที่ A[2] > A[3] สลับตำแหน่งของ 7 และ 6
ขั้นตอน 4) เราเปรียบเทียบ A[1] และ A[2] และเมื่อ A[1] < A[2] กล่าวคือ องค์ประกอบที่อยู่ติดกันด้านซ้ายจะไม่ยิ่งใหญ่อีกต่อไป ตอนนี้เราสรุปได้ว่าใส่ 6 อย่างถูกต้อง และเราหยุดอัลกอริทึมที่นี่
การเรียงลำดับการแทรกทำงานอย่างไร
การดำเนินการแทรกที่กล่าวถึงข้างต้นเป็นกระดูกสันหลังของการเรียงลำดับแบบแทรก ขั้นตอนการแทรกจะดำเนินการกับทุกองค์ประกอบ และในท้ายที่สุด เราจะได้รายการที่เรียงลำดับแล้ว
รูปตัวอย่างข้างต้นแสดงให้เห็นถึงการทำงานของการเรียงลำดับการแทรกในโครงสร้างข้อมูล ในตอนแรก มีเพียงองค์ประกอบเดียวเท่านั้นที่อยู่ในรายการย่อยที่เรียงลำดับ เช่น 4 หลังจากแทรก A[1] เช่น 3 ขนาดของรายการย่อยที่เรียงลำดับจะเพิ่มขึ้นเป็น 2
C++ โปรแกรมสำหรับการเรียงลำดับการแทรก
#include <iostream> using namespace std; int main(){ //unsorted list int unsorted[] = {9,8,7,6,5,4,3,3,2,1}; //size of list int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]); //printing unsorted list cout << "\nUnsorted: "; for(int i = 0 ; i < size_unsorted ; i++){ cout << unsorted[i] << " "; } int current_element,temp; for(int i = 1; i < size_unsorted; i++){ current_element = unsorted[i]; for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){ //swapping if current element is lesser temp = unsorted[j+1]; unsorted[j+1] = unsorted[j]; unsorted[j] = temp; } } //printing sorted list cout << "\nSorted: "; for(int i = 0 ; i < size_unsorted ; i++){ cout << unsorted[i] << " "; } return 0; }
Output:
Unsorted: 9 8 7 6 5 4 3 3 2 1 Sorted: 1 2 3 3 4 5 6 7 8 9
รหัส C สำหรับการเรียงลำดับการแทรก
#include <stdio.h> int main() { //unsorted list int unsorted[] = {9,8,7,6,5,4,3,3,2,1}; //size of list int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]); //printing unsorted list printf("\nUnsorted: "); for(int i = 0 ; i < size_unsorted ; i++){ printf("%d ", unsorted[i]); } int current_element, temp; for(int i = 1; i < size_unsorted; i++){ current_element = unsorted[i]; for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){ //swapping if current element is lesser temp = unsorted[j+1]; unsorted[j+1] = unsorted[j]; unsorted[j] = temp; } } //printing sorted list printf("\nSorted: "); for(int i = 0 ; i < size_unsorted ; i++){ printf("%d ", unsorted[i]); } return 0; }
Output:
Output: Unsorted: 9 8 7 6 5 4 3 3 2 1 Sorted: 1 2 3 3 4 5 6 7 8 9
Python โปรแกรมสำหรับการเรียงลำดับการแทรก
#unsorted list unsorted = [9,8,7,6,5,4,3,3,2,1] #size of list size_unsorted = len(unsorted) #printing unsorted list print("\nUnsorted: ", end="") for i in range(size_unsorted): print(unsorted[i], end=" ") for i in range(1, size_unsorted): current_element = unsorted[i] j = i - 1 while j >= 0 and unsorted[j] > current_element: #swapping if current element is lesser unsorted[j+1], unsorted[j] = unsorted[j], unsorted[j+1] j -= 1 #printing sorted list print("\nSorted: ", end="") for i in range(size_unsorted): print(unsorted[i], end=" ")
Output:
Unsorted: 9 8 7 6 5 4 3 3 2 1 Sorted: 1 2 3 3 4 5 6 7 8 9
คุณสมบัติของการเรียงลำดับการแทรก
นี่คือคุณสมบัติที่สำคัญของการเรียงลำดับการแทรก:
- ออนไลน์: การเรียงลำดับการแทรกสามารถเรียงลำดับองค์ประกอบตามที่ได้รับ นั่นคือถ้าเราได้เรียงลำดับรายการองค์ประกอบแล้วและผนวกองค์ประกอบเพิ่มเติมเข้ากับรายการ เราก็ไม่จำเป็นต้องรันขั้นตอนการเรียงลำดับทั้งหมดอีกครั้ง แต่เราจำเป็นต้องวนซ้ำเฉพาะองค์ประกอบที่เพิ่มเข้ามาใหม่เท่านั้น
- ในสถานที่: ความซับซ้อนของพื้นที่ของอัลกอริทึมการเรียงลำดับแบบแทรกนั้นคงที่และไม่ต้องใช้พื้นที่เพิ่มเติม อัลกอริทึมนี้จะเรียงลำดับองค์ประกอบในตำแหน่งที่ต้องการ
- เสถียร: ในการเรียงลำดับการแทรก เราจะไม่สลับองค์ประกอบหากค่าเท่ากัน ตัวอย่างเช่น สององค์ประกอบคือ x และ y เท่ากัน และ x ปรากฏก่อน y ในรายการที่ไม่เรียงลำดับ จากนั้นในรายการที่เรียงลำดับ x จะปรากฏก่อน y ทำให้การเรียงลำดับการแทรกมีความเสถียร
- ปรับตัว: A อัลกอริทึมการเรียงลำดับ เป็นแบบปรับตัวได้หากใช้เวลาน้อยลงหากองค์ประกอบอินพุตหรือชุดย่อยขององค์ประกอบได้รับการเรียงลำดับแล้ว ตามที่เราได้กล่าวไว้ข้างต้น เวลาดำเนินการที่ดีที่สุดของการเรียงลำดับแบบแทรกคือ O(N) และเวลาดำเนินการที่แย่ที่สุดคือ O(N^2) การเรียงลำดับแบบแทรกเป็นหนึ่งในอัลกอริทึมการเรียงลำดับแบบปรับตัวได้
ความซับซ้อนของการเรียงลำดับแบบแทรก
ความซับซ้อนของอวกาศ
การเรียงลำดับแบบแทรกไม่จำเป็นต้องใช้พื้นที่พิเศษเพื่อเรียงลำดับองค์ประกอบ ความซับซ้อนของพื้นที่จะคงที่ นั่นคือ O(1)
ความซับซ้อนของเวลา
เนื่องจากการเรียงลำดับแบบแทรกจะวนซ้ำแต่ละองค์ประกอบพร้อมกัน จึงต้องใช้การเรียงลำดับ N-1 ครั้งในการเรียงลำดับ N องค์ประกอบ ในแต่ละรอบ อาจสลับเป็นศูนย์หากองค์ประกอบได้รับการเรียงลำดับแล้ว หรือสลับหากองค์ประกอบได้รับการจัดเรียงในลำดับจากมากไปน้อย
- สำหรับบัตรผ่าน 1 ค่าสวอปขั้นต่ำที่ต้องการคือศูนย์ และค่าสวอปสูงสุดที่ต้องการคือ 1
- สำหรับบัตรผ่าน 2 ค่าสวอปขั้นต่ำที่ต้องการคือศูนย์ และค่าสวอปสูงสุดที่ต้องการคือ 2
- สำหรับ pass N ค่า swap ขั้นต่ำที่ต้องการคือศูนย์ และค่า swap สูงสุดที่ต้องการคือ N
- การสลับขั้นต่ำคือศูนย์ ดังนั้นความซับซ้อนของเวลาที่ดีที่สุดคือ O(N) สำหรับการวนซ้ำ N ครั้ง
- การสลับสูงสุดทั้งหมดคือ (1+2+3+4+..+N) คือ N(N+1)/2 ความซับซ้อนของเวลาที่แย่ที่สุดคือ O(N^2)
นี่คือความซับซ้อนของเวลาที่สำคัญของการเรียงลำดับแบบแทรก:
- ความซับซ้อนของกรณีที่เลวร้ายที่สุด: O(n2): การเรียงลำดับอาร์เรย์จากมากไปน้อยเมื่อเรียงลำดับจากน้อยไปหามากถือเป็นสถานการณ์ที่เลวร้ายที่สุด
- ความซับซ้อนของเคสที่ดีที่สุด: O(n): ความซับซ้อนของกรณีที่ดีที่สุดจะเกิดขึ้นเมื่ออาร์เรย์ได้รับการเรียงลำดับแล้ว ลูปด้านนอกทำงาน n ครั้ง ในขณะที่ลูปด้านในไม่ทำงานเลย มีการเปรียบเทียบเพียง n ครั้ง ดังนั้น ในกรณีนี้ ความซับซ้อนจะเป็นแบบเส้นตรง
- ความซับซ้อนของเคสโดยเฉลี่ย: O(n2): มันเกิดขึ้นเมื่อองค์ประกอบของอาเรย์เกิดขึ้นตามลำดับที่สับสน ซึ่งไม่ขึ้นหรือลง
สรุป
- การเรียงลำดับการแทรกเป็นวิธีอัลกอริธึมการเรียงลำดับที่อิงจากการเปรียบเทียบ
- เป็นเทคนิคการเรียงลำดับที่มีความเสถียร จึงไม่เปลี่ยนลำดับสัมพัทธ์ขององค์ประกอบที่เท่ากัน
- ในแต่ละองค์ประกอบ การดำเนินการแทรกจะถูกใช้เพื่อแทรกองค์ประกอบในรายการย่อยที่เรียงลำดับแล้ว
- การเรียงลำดับการแทรกเป็นอัลกอริทึมการเรียงลำดับแบบแทนที่
- ความซับซ้อนของเวลาโดยเฉลี่ยที่แย่ที่สุดในการเรียงลำดับแบบแทรกคือกำลังสอง หรือ O(N^2)
- การเรียงลำดับการแทรกไม่จำเป็นต้องมีช่องว่างเสริม