1. 程式人生 > >經典演算法之兩個有序單鏈表合併

經典演算法之兩個有序單鏈表合併

/************************
author's email:[email protected]
date:2017.12.31
單鏈表應用
************************/
/*
A和B是兩個單鏈表(帶表頭結點),其中元素遞增有序。設計一個演算法,將A和B歸成一
個按元素值非遞減有序的連結串列C,C由A和B中的結點組成。
*/
#include <iostream>
using namespace std;
#define maxSize 10
typedef struct LNode {
	int data;
	struct LNode *next;
}LNode;
void createListR(LNode *&p, int *a, int n);//尾插法構造單鏈表
void printList(LNode *p);
void createListF(LNode *&p, int *a, int n);//頭插法構造單鏈表
void bubbleSort(LNode *L);//按結點值的大小氣泡排序,使之呈遞增序列
void merge(LNode *A, LNode *B, LNode *&C);//將A和B合併成非遞減有序的C,利用尾插法
void main() {
	int a[maxSize] = { 15,46,47,29,19,23,68,79,115,784 };
	int b[maxSize] = { 45,11,78,49,56,113,456,741,999,35 };
	LNode *A,*B,*C;
	A = (LNode*)malloc(sizeof(LNode));
	A->next = NULL;
	B = (LNode*)malloc(sizeof(LNode));
	B->next = NULL;
	C = (LNode*)malloc(sizeof(LNode));
	C->next = NULL;


	cout << "頭插法結果為:" << endl;
	createListF(A, a, maxSize);//頭插法
	printList(A->next);

	cout << "尾插法結果為:" << endl;
	createListR(B, b, maxSize);//尾插法
	printList(B->next);

	cout << "連結串列A遞增排序後為:" << endl;
	bubbleSort(A);
	printList(A->next);


	cout << "連結串列B遞增排序後為:" << endl;
	bubbleSort(B);
	printList(B->next);


	cout << "將A和B合併成非遞減有序的C連結串列後:" << endl;
	merge(A, B, C);
	printList(C->next);
}
void createListR(LNode *&p, int *a, int n) {//尾插法構造單鏈表
	LNode *s, *r;
	int i;
	r = p;
	for (i = 0; i < n; ++i) {
		s = (LNode*)malloc(sizeof(LNode));
		s->data = a[i];
		r->next = s;
		r = r->next;
	}
	r->next = NULL;
}
void printList(LNode *p) {//輸出連結串列
	if (p->next == NULL)
		cout << "連結串列為空!" << endl;
	else {
		while (p != NULL) {
			cout << p->data << ' ';
			p = p->next;
		}
		cout << endl;
	}
}
void createListF(LNode *&p, int *a, int n) {//頭插法構造連結串列
	LNode *s;
	int i;
	for (i = 0; i < n; ++i) {
		s = (LNode*)malloc(sizeof(LNode));
		s->data = a[i];
		s->next = p->next;
		p->next = s;
	}
}
void bubbleSort(LNode *L) {
	LNode *p, *tail, *next;
	int temp;
	if (L->next == NULL)
		cout << "連結串列為空!" << endl;
	else {
		for (p = L->next; p != NULL; p = p->next)    /*尾指標初始化*/
			;
		tail = p;
		while (tail != L->next)
		{
			for (p = L->next; p->next != tail; p = p->next)
			{
				next = p->next;
				if (p->data > next->data)    /*相鄰節點比較,資料交換*/
				{
					temp = p->data;
					p->data = next->data;
					next->data = temp;
				}
			}
			tail = p;    /* p->next == tail,即把tail往前移動一位 */
		}
	}
}
void merge(LNode *A, LNode *B, LNode *&C) {
	LNode *p = A->next;   //p來跟蹤A的最小值結點
	LNode *q = B->next;   //q來跟蹤B的最小值結點
	LNode *r;             //r始終指向C的終端結點
	C = A;                //A的頭結點來做C的頭結點
	//C->next = NULL;
	free(B);
	r = C;
	while (p != NULL&&q != NULL) {//當p、q都不為空時,選取p與q所指結點中的較小者插入C的尾部
		//尾插法建立單鏈表
		if (p->data <= q->data) {
			r->next = p;
			p = p->next;
			r = r->next;
		}
		else
		{
			r->next = q;
			q = q->next;
			r = r->next;
		}
	}


	//以下兩個if語句將剩餘的結點連結在C的尾部
	if (p != NULL)
		r->next = p;
	if (q != NULL)
		r->next = q;
}