排序链表的n种解法

一、冒泡排序

class Solution {
public:
	ListNode* sortList(ListNode* head) {
		ListNode* dummpyHead = new ListNode(-1);
		dummpyHead->next = head;
		ListNode* temp = dummpyHead;
		int len = 0;
        //统计链表长度,顺便进行将最大值放在末尾
		while (temp->next && temp->next->next) {
			if (temp->next->val > temp->next->next->val) {
				ListNode* node = temp->next;
				temp->next = node->next;
				node->next = node->next->next;
				temp->next->next = node;
			}
			temp = temp->next;
			len++;
		}
        //再进行n-1次排序,依此把最大值后移
		for (int i = 0; i < len - 1; i++) {
			temp = dummpyHead;
			while (temp->next->val && temp->next->next->val) {
				if (temp->next > temp->next->next) {
					ListNode* node = temp->next;
					temp->next = node->next;
					node->next = node->next->next;
					temp->next->next = node;
				}
				temp = temp->next;
			}
		}
		return dummpyHead->next;
	}
};

二、归并排序

归并排序需要注意节点的断开。

class Solution {
public:
	ListNode* sortList(ListNode* head) {
		return sortList(head, nullptr);
	}
	ListNode* sortList(ListNode* head, ListNode* tail) {
		if (head == nullptr)return head;
        //注意把节点断开
		if (head->next == tail) {
			head->next = nullptr;
			return head;
		}
		ListNode*slow = head, *fast = head->next;
        //快慢指针找中点
		while (fast != tail) {
			slow = slow->next;
			if (fast->next != tail) {
				fast = fast->next->next;
			}
			else {
				break;
			}
		}
		ListNode* mid = slow;
		ListNode* head1 = sortList(head, mid);
		ListNode* head2 = sortList(mid,tail);
		return merge(head1, head2);
	}
    //合并两个有序链表
	ListNode* merge(ListNode* l1, ListNode* l2) {
		ListNode* head = new ListNode(-1);
		ListNode* temp = head;
		while (l1 || l2) {
			if (l1 == nullptr) {
				temp->next = l2;
				break;
			}
			if (l2 == nullptr) {
				temp->next = l1;
				break;
			}
			if (l1->val <= l2->val) {
				temp->next = l1;
				l1 = l1->next;
			}
			else {
				temp->next = l2;
				l2 = l2->next;
			}
			temp = temp->next;
		}
		return head->next;
	}
};

三、快速排序

class Solution {
private:
	vector<ListNode*>vec;
public:

	void sort(int left, int right) {
		if (left < right) {
            //随机选取一个位置作为标兵,放在对应位置
			int ran = rand() % (right - left + 1) + left;
			swap(vec[ran], vec[right]);
			int privot = vec[right]->val;
			int i = left - 1;
			for (int j = left; j < right; ++j) {
				if (vec[j]->val <= privot) {
					i++;
					swap(vec[i], vec[j]);
				}
			}
			swap(vec[i + 1], vec[right]);
			int pos = i + 1;

            //跳过与标兵位置相同的值
			int rNum = pos - 1;
			int lNum = pos + 1;
			while (rNum >= left && vec[rNum]->val == vec[pos]->val) {
				rNum--;
			}
			while (lNum <= right && vec[lNum]->val == vec[pos]->val) {
				lNum++;
			}
            
            //进行下一次排序
			sort(left, rNum);
			sort(lNum, right);
		}

	}
	ListNode* sortList(ListNode* head) {
		srand((unsigned)time(NULL));
		if (head == nullptr)return head;
        //把链表的节点放入数组并使用快速排序
		ListNode* temp = head;
		while (temp) {
			vec.push_back(temp);
			temp = temp->next;
		}
		int n = vec.size();
		sort(0, n - 1);
        //把排好序的数组还原成链表
		ListNode* dummyHead = new ListNode(-1);
		temp = dummyHead;
		for (int i = 0; i < n; i++) {
			temp->next = vec[i];
			temp = temp->next;
		}
		temp->next = nullptr;

		return dummyHead->next;
	}
};

四、堆排序

class Solution {
private:
	vector<ListNode*>vec;
public:
	void maxHeap(int i, int len) {
		for (; i * 2 + 1 <= len;) {
			int large = i;
			if (i * 2 + 1 <= len && vec[i * 2 + 1]->val > vec[large]->val) large = i * 2 + 1;
			if (i * 2 + 2 <= len && vec[i * 2 + 2]->val > vec[large]->val)large = i * 2 + 2;
			if (large == i) {
				break;
			}
			else {
				swap(vec[i], vec[large]);
				i = large;
			}
		}
	}
	void buildHeap() {
		int len = vec.size() - 1;
		for (int i = len / 2; i >= 0; --i) {
			maxHeap(i, len);
		}
	}
	void sort() {
		buildHeap();
		int len = vec.size() - 1;
		for (int i = len; i >= 0; --i) {
			swap(vec[i], vec[0]);
			len--;
			maxHeap(0, len);
		}
	}

	ListNode* sortList(ListNode* head) {
		if (head == nullptr)return nullptr;
		//把链表的节点放入数组并使用堆排序
        ListNode* temp = head;
		while (temp) {
			vec.push_back(temp);
			temp = temp->next;
		}
		int n = vec.size();
		sort();
        //把排好序的数组还原成链表
		ListNode* dummyHead = new ListNode(-1);
		temp = dummyHead;
		for (int i = 0; i < n; i++) {
			temp->next = vec[i];
			temp = temp->next;
		}
		temp->next = nullptr;
		return dummyHead->next;
	}
};

五、放入数组使用sort()排序

class Solution {
public:
	ListNode* sortList(ListNode* head) {
		vector<ListNode*>vec;
		ListNode* temp = head;
		while (temp) {
			vec.push_back(temp);
			temp = temp->next;
		}
		sort(vec.begin(), vec.end(), [](ListNode* a, ListNode* b) {
			return a->val < b->val; //这里用小于,如何是等于很多相等的还要移动
		});
		ListNode* dummyHead = new ListNode(-1);
		temp = dummyHead;
		for (int i = 0; i < vec.size(); i++) {
			temp->next = vec[i];
			temp = temp->next;
		}
		temp->next = nullptr;
		return dummyHead->next;
	}
};

六、multimap进行排序

class Solution {
public:
	ListNode* sortList(ListNode* head) {
        //把<值,节点>插入multimap的过程是一个红黑树,因此会自动按照键值排序
		ListNode* temp = head;
		multimap<int, ListNode*>map;
		while (temp) {
			map.insert({ temp->val,temp });
			temp = temp->next;
		}
        //把排好序的节点连接起来
		ListNode* dummyHead = new ListNode(-1);
		ListNode* curr = dummyHead;
		for (auto it = map.begin(); it != map.end(); it++) {
			curr->next = (*it).second;
			curr = curr->next;
		}
		curr->next = nullptr;
		return dummyHead->next;
	}
};

七、总结

六种方法都是普通排序数组可以用到的方法,这里套用在排序链表上。其中冒泡排序的时间复杂度很高不能通过,其他均可通过。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值