Computer >> 컴퓨터 >  >> 프로그램 작성 >> C++

연결 목록에서 병합 정렬 알고리즘을 구현하는 C++ 프로그램


병합 정렬 기술은 분할 정복 기술을 기반으로 합니다. while 데이터 세트를 더 작은 부분으로 나누고 정렬된 순서로 더 큰 부분으로 병합합니다. 이 알고리즘은 최악의 경우에도 시간 복잡도가 낮기 때문에 최악의 경우에도 매우 효과적입니다.

연결 목록은 병합 정렬을 사용하여 매우 효율적으로 정렬할 수 있습니다. 연결 목록의 경우 병합 작업은 매우 간단합니다. 링크를 업데이트하여 병합하기만 하면 됩니다. 이 섹션에서는 이 접근 방식을 사용하여 연결 목록을 정렬하는 방법을 살펴보겠습니다.

병합 정렬 기법의 복잡성

  • 시간 복잡성 - 모든 경우에 대해 O(n log n)

  • 공간 복잡성 - 오(n)

입력 − 정렬되지 않은 목록:14 20 78 98 20 45출력 − 정렬 후 배열:14 20 20 45 78 98

알고리즘

병합 목록(ll1, ll2)

입력 − 두 개의 연결 목록 ll1과 ll2가 필요합니다.

출력 - 병합된 목록

ll1이 비어 있으면 시작하고, ll2가 비어 있으면 ll2를 반환하고, data(ll1) <=data(ll2)이면 ll1을 반환하고 new_head =ll1; next(new_head) =mergeList(next(ll1), ll2) else new_head =ll2; next(new_head) =mergeList(ll1, next(ll2)) return new_headEnd

split_list(시작, ll1, ll2)

입력 - 연결 목록의 시작 포인터, 두 개의 출력 인수 ll1 및 ll2

출력 − 연결 목록에서 생성된 두 개의 연결 목록

느리게 시작 :=빠르게 시작 :=fast가 null이 아닌 동안 다음(start), fast가 null이 아니면 fast :=next(fast), 이후 slow :=next(slow) fast :=next(fast) end while ll1 :=start ll2 :=next(slow) next(slow) :=nullEnd

병합 정렬(시작)

입력 - 연결 리스트

출력 - 정렬된 연결 리스트

Begin head =head가 null이거나 next(head)가 null이면 start, split_list(head, ll1, ll2)를 반환 mergeSort(ll1) mergeSort(ll2) start :=mergeList(ll1, ll2)End

소스 코드(C++)

#include이름 공간 사용 std;class node { //데이터와 다음 주소를 저장할 노드 정의 public:int data; 노드 *다음;}; 무효 표시(클래스 노드* 시작) { 노드* p =시작; // 현재 노드를 헤드로 설정 while(p !=NULL) { //현재 노드가 NULL이 아닐 때까지 순회 cout <

data <<" "; p =p -> 다음; // 다음 노드로 이동 }}node* getNode(int d) { node* temp =new node; 온도 -> 데이터 =d; 임시 -> 다음 =NULL; return temp;}node* mergeList(node* ll1, node* ll2) { //정렬된 두 목록을 병합하는 함수 node* newhead =NULL; if(ll1 ==NULL) 반환 ll2; if(ll2 ==NULL) 반환 ll1; //재귀적으로 목록 병합 if(ll1 -> data <=ll2 -> data) { newhead =ll1; newhead -> 다음 =mergeList(ll1->next,ll2); } else { 뉴헤드 =ll2; newhead -> 다음 =mergeList(ll1,ll2->next); } return newhead;}void splitList(node* start, node** ll1,node** ll2) { //flyod의 거북이 알고리즘과 유사 node* slow =start; node* fast =시작 -> 다음; while(빠른!=NULL) { 빠름 =빠름 -> 다음; if(빠른!=NULL) { 느린 =느린 -> 다음; 빠름 =빠름 -> 다음; } } *ll1 =시작; *ll2 =느림 -> 다음; // 느린 분할 -> next =NULL;}void mergeSort(node** start) { node* head =*start; 노드* ll1,*ll2; //기본 경우 if(head ==NULL || head->next ==NULL) { return; } splitList(머리,&ll1,&ll2); //목록을 두 부분으로 분할 //왼쪽 및 오른쪽 하위 목록 정렬 mergeSort(&ll1); mergeSort(&ll2); //정렬된 두 리스트 병합 *start =mergeList(ll1,ll2); return;}int main() { cout <<"연결 리스트 생성:" <> k; 노드* 헤드 =getNode(k); //구성 목록, 첫 번째 노드 cin>> k; 온도 =머리; 동안(k) { 현재 =getNode(k); temp -> next =curr;//각 노드 추가 temp =temp -> next; 신>> k; } cout<<"정렬 전:" <

출력

연결 목록 만들기:목록 작성을 중지하려면 0을 입력하고, 그렇지 않으면 임의의 정수를 입력합니다.8954156474981024260정렬 전:89 54 15 64 74 98 10 24 26정렬 후:10 15 24 26 54 894 97