手把手教你实现链表的归并排序
来源:互联网 发布:cocos2d 源码 编辑:程序博客网 时间:2024/06/05 08:33
参考资料:《数据结构与算法分析》(第三版英文版)
书本题目:7.20 (269页)
这个题目的意思很简单,就是实现链表的归并排序
先实现一个简单的节点Node结构
struct Node {int data;Node* next;Node(int val) {data = val;next = NULL;}Node(){data = 0;next = NULL;}};
再到链表
struct List {Node* head;Node* tail;List(int val){head = new Node(val);tail = head;}void append(int val){tail->next = new Node(val);tail = tail->next;}};在main函数里面测试链表是否成功
int main() {List list = List(6);list.append(3);list.append(4);list.append(9);list.append(8);list.append(3);list.append(42);list.append(25);list.append(51);list.append(30);Node* test = list.head;for (int i = 0; i < 10; i++){cout << test->data << " ";test = test->next;}system("pause");}运行程序,成功按顺序打印出数值
下面是链表归并函数的实现
Node* listMergeSort(Node* head) //传入需要归并排序的链表的头指针{ //一个元素就返回if (head->next == NULL)return head;//使用 slow-fast方法找到链表的中间位置,注意这里写的链表的头节点是非空的,即头节点也是存贮数据的Node* fast = head->next; // fast指向第2个节点Node* slow = head; // slow指向第1个节点while (fast != NULL&&fast->next != NULL){fast = fast->next->next; //fast每次走两步slow = slow->next;//slow每次走一步,这样slow就会到lian'biao中点}//slow最后指向有n个元素的链表的第n/2个元素。如一共6个元素,slow指向第3个,一共5个元素,slow指向第2个。Node* left = head;Node* right = slow->next;slow->next = NULL;//但是实际上将链表截断,左边的部分从第1个开始,右边的要从第4个(共6个)或者第3个(共5个)开始,所以有right=slow->next;//假设上面截断的左右两个子链表调用归并排序后变成了排好序(new,新)的“新”左右两个链表,然后开始归并Node* newLeft = listMergeSort(left);Node* newRight = listMergeSort(right);Node * newList ; //注意指针tail才是后面进行操作的指针,newList是为了保存起点Node * tail ;if (newLeft->data < newRight->data){newList = newLeft;newLeft = newLeft->next;}else{newList = newRight;newRight = newRight->next;}tail=newList ;tail->next = NULL;//以上代码是向newList的第一个节点存入左右两个链表的头节点的较小的元素while (newLeft != NULL|| newRight != NULL)//在&&和||之间踩了大坑,调了一个多小时的bug,让我骂一句真是mmp{if (newLeft == NULL)//左边全部接完了{tail->next = newRight; //右边就直接整条链表接上去newRight = NULL;}else if (newRight == NULL) {//同理,右边接完了tail->next = newLeft; //左边就直接整条链表接上去,复杂度为O(1),操作爽yynewLeft = NULL;}else if (newLeft->data < newRight->data) {tail->next = newLeft;//上面接一整个链表,这里就是接链表中单个元素的操作newLeft = newLeft->next; tail = tail->next;tail->next = NULL;}else {tail->next = newRight;newRight = newRight->next;tail = tail->next;tail->next = NULL;}}return newList; //返回新接好的List,美滋滋。}再贴上main函数代码
int main() {List list = List(6);list.append(3);list.append(4);list.append(9);list.append(8);list.append(3);list.append(42);list.append(25);list.append(51);list.append(30);Node* test = list.head;for (int i = 0; i < 10; i++){cout << test->data << " ";test = test->next;}Node* newHead = listMergeSort(list.head);cout << endl;Node * temp ;for (int i = 0; i < 10; i++){cout << newHead->data << " ";temp = newHead;if(newHead->next!=NULL) //这里有个坑,踩过,读者试试注释掉这一个判断语句newHead = newHead->next;delete temp; //注意回收内存}system("pause");}
最后贴上完整代码
# include <iostream>using namespace std;struct Node {int data;Node* next;Node(int val) {data = val;next = NULL;}Node(){data = 0;next = NULL;}};struct List {Node* head;Node* tail;List(int val){head = new Node(val);tail = head;}void append(int val){tail->next = new Node(val);tail = tail->next;}};Node* listMergeSort(Node* head)// n list里面节点的个数{//if (head->next == NULL) //一个元素就返回if (head->next == NULL)return head;Node* fast = head->next;Node* slow = head;while (fast != NULL&&fast->next != NULL){fast = fast->next->next;slow = slow->next;}Node* left = head;Node* right = slow->next;slow->next = NULL;Node* newLeft = listMergeSort(left);Node* newRight = listMergeSort(right);Node * newList ;Node * tail ;if (newLeft->data < newRight->data){newList = newLeft;newLeft = newLeft->next;}else{newList = newRight;newRight = newRight->next;}tail=newList ;tail->next = NULL;while (newLeft != NULL|| newRight != NULL){if (newLeft == NULL){tail->next = newRight;newRight = NULL;}else if (newRight == NULL) {tail->next = newLeft;newLeft = NULL;}else if (newLeft->data < newRight->data){tail->next = newLeft;newLeft = newLeft->next;tail = tail->next;tail->next = NULL;}else {tail->next = newRight;newRight = newRight->next;tail = tail->next;tail->next = NULL;}}Node *temp = newList;return newList;}int main() {List list = List(6);list.append(3);list.append(4);list.append(9);list.append(8);list.append(3);list.append(42);list.append(25);list.append(51);list.append(30);Node* test = list.head;for (int i = 0; i < 10; i++){cout << test->data << " ";test = test->next;}Node* newHead = listMergeSort(list.head); //这里把list的头节点直接进去了2333333,不优雅.。。。cout << endl;Node * temp ;for (int i = 0; i < 10; i++){cout << newHead->data << " ";temp = newHead;if(newHead->next!=NULL) newHead = newHead->next;delete temp; }system("pause");}
一共137行代码,感觉实现还是蛮优雅的呵呵~(臭不要脸),当然在给那个NewList的头节点加数据的时候代码有点冗余。。。
链表从头节点来分有两种,我的是头节点保存元素的那类链表。
开始时想把 Node* listMergeSort(Node* head) 这个函数的参数带入一个整形参数n (链表元素个数)的,这样好通过n/2求链表中点,后来看到这个博客里面的slow-fast方法。果断用这个方法2333333
参考资料http://www.cnblogs.com/zhanghaiba/p/3534521.html
阅读全文
0 0
- 手把手教你实现链表的归并排序
- 手把手教你写一个归并排序
- 手把手教你 ----JNI的基础实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- 归并排序的实现
- docker使用
- DOS命令常用
- ArrayList、LinkedList、HashMap的底层实现
- 数组排序
- 信号处理学习笔记(二)Decimation信号抽取
- 手把手教你实现链表的归并排序
- 修改/etc/profile的readonly参数方法
- Sign of Matrix UVA
- L1-002. 打印沙漏
- 一次JVM调优实战
- leetcode: 14. Longest Common Prefix
- Linux系统之lvm的应用
- 02项目开发计划(机房收费系统V2.1)
- 百度UEditor编辑器视频相关bug汇总和稳定解决方案