对单链表的归并排序的C++实现

前言

记录用C++实现基于单链表的归并排序

代码

一共三个文件SingleLinkedList.h, CNode.h以及main.cpp。
首先是CNode.h

#ifndef _NODE_H__
#define _NODE_H__

class CNode{
private:
	int data;
	CNode *nextNode;
public:
	CNode();
	void setData(int iData);
	int getData() const;
	void setNextNode(CNode *nextNode);
	CNode* getNextNode() const;
};

#endif

接下来是SingleLinkedList.h,复用的之前写过的代码,添加了一些方法。

#ifndef _SINGLE_LINKEDLIST_H__
#define _SINGLE_LINKEDLIST_H__
#include "CNode.h"
//#include "SingleLinkedList.cpp"

class SingleLinkedList{

private:
	CNode *firstNode;
		
public:
	
	 SingleLinkedList();
	~SingleLinkedList();

	void insertAtTheFront(int data);

	void insertAtTheMiddle(int data, int position);

	void insertAtTheEnd(int data);

	void deleteFromTheFront();

	void deleteFromTheMiddle(int position);
	
	void deleteFromTheEnd();

	bool search(int data);

	void display();

	CNode* merge(CNode *p,CNode *q);

	CNode* mergeSort(CNode *head);

	CNode* getMid(CNode *head);

	CNode* mergesort();

};

#endif

最后是main.cpp, 针对单链表的实现主要复用了之前C++实现单链表的代码,不过发现并修改了不少问题,找时间回头会把那篇博客也改一下。

#include <iostream>
#include "CNode.h"
#include "SingleLinkedList.h"
using namespace std;
CNode::CNode(){
	this->nextNode = NULL;
};
void CNode::setData(int iData){
	this->data = iData;
};
int CNode::getData() const{
	return data;
}
void CNode::setNextNode(CNode *nextNode){
	this->nextNode = nextNode;
};
CNode* CNode::getNextNode() const{
	return nextNode;
};
SingleLinkedList::SingleLinkedList(){
	firstNode = NULL;
	cout << "SUCCESSFULLY BUILD" << endl;
};
SingleLinkedList::~SingleLinkedList(){
};

void SingleLinkedList::insertAtTheFront(int data){
	CNode *p = new CNode;
	p->setData(data);
	if (firstNode == NULL) {
		firstNode = new CNode;
		this->firstNode->setData(data);
	}
	else {
		p->setNextNode(firstNode);
		this->firstNode = p;
	}
};

void SingleLinkedList::insertAtTheMiddle(int data, int position){
	//add node s at the position
	CNode *p = firstNode;
	CNode *s = new CNode;
	s->setData(data);
	if (firstNode == NULL) {
		firstNode = new CNode;
		this->firstNode->setData(data);
		return;
	}
	if (position == 1){
		insertAtTheFront(data);
		return;
	}
	for (int i = 0; i < position - 2; i++){
		if (p->getNextNode() != NULL) p = p->getNextNode();
		else { 
			cout << "ERROR";
			return;
		}
	}
	s->setNextNode(p->getNextNode());
	p->setNextNode(s);

};

void SingleLinkedList::insertAtTheEnd(int data){
	CNode *p = firstNode;
	CNode *s = new CNode;
	s->setData(data);
	while (p->getNextNode() != NULL){
		p = p->getNextNode();
	}
	p->setNextNode(s);
};

void SingleLinkedList::deleteFromTheFront(){
	if (firstNode == NULL) return;
	else if (firstNode->getNextNode() == NULL){
		firstNode = NULL;
		return;
	}
	CNode *p = firstNode->getNextNode();
	firstNode = p;
};

void SingleLinkedList::deleteFromTheMiddle(int position){
	CNode *p = firstNode;
	CNode *s = new CNode;
	if (firstNode == NULL) return;
	if (position == 1){
		deleteFromTheFront();
		return;
	}
	for (int i = 0; i < position - 2; i++){
		if (p->getNextNode() != NULL) p = p->getNextNode();
		else {
			cout << "ERROR";
			return;
		}
	}
	p->setNextNode(p->getNextNode()->getNextNode());
};

void SingleLinkedList::deleteFromTheEnd(){
	CNode *p = firstNode;
	if (p == NULL){
		cout << "ERROR" << endl;
		return;
	}
	if (p->getNextNode() == NULL){
		firstNode = NULL;
		return;
	}
	while (p->getNextNode()->getNextNode() != NULL) p = p->getNextNode();
	p->setNextNode(NULL);
};

bool SingleLinkedList::search(int data){
	CNode *p = firstNode;
	while (p->getNextNode() != NULL){
		if (p->getData() == data) return true;
		p = p->getNextNode();
	}
	if (p->getData() == data) return true;
	else return false;
};

void SingleLinkedList::display(){
	//display the single linked list
	CNode *p = firstNode;
	int i = 0;
	while (p->getNextNode() != NULL){
		cout << ++i << ":" << p->getData() << endl;
		p = p->getNextNode();
	}
	cout << ++i << ":" << p->getData() << endl;
};

CNode* SingleLinkedList::getMid(CNode* head){
	//find the middle node
	if (!head) return NULL;
	if (!head->getNextNode()) return head;

	CNode *slow = head;
	CNode *fast = head->getNextNode();

	while (fast && fast->getNextNode())
	{
		slow = slow->getNextNode();
		fast = fast->getNextNode()->getNextNode();
	}
	return slow;
}
CNode* SingleLinkedList::merge(CNode *a, CNode *b) {
	//merge two sorted arrays
	if (a == NULL) return b;
	if (b == NULL) return a;
	CNode *ret = NULL;
	CNode *tail = NULL;

	ret = new CNode;
	tail = ret;
	while (a && b)
	if (a->getData() < b->getData())
	{
		tail->setNextNode(a);
		tail = tail->getNextNode();
		a = a->getNextNode();
	}
	else
	{
		tail->setNextNode(b);
		tail = tail->getNextNode();
		b = b->getNextNode();
	}
	if (a)
		tail->setNextNode(a);
	if (b)
		tail->setNextNode(b);

	CNode *del = ret;
	ret = ret->getNextNode();
	delete del;
	return ret;
}

CNode* SingleLinkedList::mergeSort(CNode *head) { 
	//mergesort from the node head
	if (!head) return NULL;
	if (!head->getNextNode()) return head;

	CNode *mid = getMid(head);
	CNode *nextPart = NULL;
	if (mid)
	{
		nextPart = mid->getNextNode();
		mid->setNextNode(NULL);
	}

	return merge(
		mergeSort(head),
		mergeSort(nextPart)
		);
}

CNode* SingleLinkedList::mergesort(){
	//merge sort the whole single linked list
	return firstNode=mergeSort(firstNode);
}
int main(){
	SingleLinkedList theList;
	theList.insertAtTheFront(44);
	theList.insertAtTheFront(88);
	theList.insertAtTheFront(66);
	theList.insertAtTheFront(22);
	theList.insertAtTheFront(55);
	theList.insertAtTheFront(11);
	theList.insertAtTheFront(33);
	theList.insertAtTheFront(99);
	theList.display();
	theList.mergesort();
	theList.display();
}

注意点

只要理解了递归的思想,归并排序总的来说还是比较好理解的,上核心代码:

CNode* SingleLinkedList::mergeSort(CNode *head) { 
	//mergesort from the node head
	if (!head) return NULL;
	if (!head->getNextNode()) return head;

	CNode *mid = getMid(head);
	CNode *nextPart = NULL;
	if (mid)
	{
		nextPart = mid->getNextNode();
		mid->setNextNode(NULL);
	}

	return merge(
		mergeSort(head),
		mergeSort(nextPart)
		);
}

比数组的归并要难实现一点点,但原理没变。找到中间结点,分别对左边和右边的链表进行归并排序,最后将左右两个链表归并起来。注意递归头,在head无后继结点时生效。
自此,我们的目标就比较明确了。
1.从结点Node开始的归并排序 即上面的mergeSort()
2.找到中间结点,即getMid()
3.归并两个有序单链表,即merge()

特地把找中间节点拿出来说,因为这段找中间节点的代码是从网上找来的,我觉得很有新意也很聪明:

CNode* SingleLinkedList::getMid(CNode* head){
	//find the middle node
	if (!head) return NULL;
	if (!head->getNextNode()) return head;

	CNode *slow = head;
	CNode *fast = head->getNextNode();

	while (fast && fast->getNextNode())
	{
		slow = slow->getNextNode();
		fast = fast->getNextNode()->getNextNode();
	}
	return slow;
}

最后就是归并的merge写法了,将两个链表从左向右遍历,每次都取最小的一个拿出来,直至遍历完成。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单链表归并排序是一种常见的排序算法,它通过分治的思想将链表分成若干个子链表,然后对每个子链表进行排序,最后将这些有序的子链表合并成一个有序的链表。 具体实现步骤如下: 1. 定义一个函数merge(head1, head2),用于将两个有序链表head1和head2合并成一个有序链表,并返回合并后的链表头节点。 2. 定义一个函数sortList(head),用于将链表head排序,并返回排序后的链表头节点。排序的具体实现可以按以下步骤进行: a. 如果链表为空或只有一个节点,则直接返回。 b. 定义两个指针slow和fast,分别指向链表头节点和中间节点。使用快慢指针的方链表分成两个子链表。 c. 递归调用sortList函数对两个子链表进行排序。 d. 调用merge函数将两个有序的子链表合并成一个有序的链表,并返回合并后的链表头节点。 3. 最后,调用sortList函数对整个链表进行排序即可。 下面是单链表归并排序的Python代码实现: ```python class ListNode: def __init__(self, x): self.val = x self.next = None def merge(head1, head2): if not head1: return head2 if not head2: return head1 if head1.val < head2.val: head1.next = merge(head1.next, head2) return head1 else: head2.next = merge(head1, head2.next) return head2 def sortList(head): if not head or not head.next: return head slow, fast = head, head.next while fast and fast.next: slow = slow.next fast = fast.next.next mid = slow.next slow.next = None left = sortList(head) right = sortList(mid) return merge(left, right) ``` 时间复杂度:O(nlogn)。 空间复杂度:O(logn),因为归并排序使用了递归,所以需要O(logn)的栈空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值