本文共 2374 字,大约阅读时间需要 7 分钟。
首先,回忆一下数组的快排步骤:
函数参数: 数组arr, 起点nLow, 终点nHigh 功能: 把nLow 至 nHigh 段的数组进行一次快排。 结果:【比nMark小的元素】nMark【比nMark大的元素】
#区间分割法 1. 取最后一个元素为标记,用nSmall标记小区间大小,i 用来遍历数组; 2. 遍历值小于标记值:小区间的下一个不是当前位置,需要交换,否则直接小区间位置+1 3. 如此循环到 标记位置(最后一个元素) 4. 将标记元素(即最后一个元素)放到 s+1 的位置;
数组快排的链接:
由此,我们写一下链表的步骤: 函数参数: List*pBegin,List*pEnd
1. 取第一个元素作为标记元素, 用pSmall指针,指向首元素;2. 使用pTemp遍历链表, 找到找到小于标记的元素,将pSmall移到下一位置; 若下一个位置不是当前位置, 将pSmall 和 pTemp 的元素进行交换;3. 重复 2, 直到pTemp == pEnd;4. 此时pSmall 指向小链表的最后一个元素, 将这个元素和标记元素(链表头)进行交换;5. 分别递归前半部分和后半部分;
先上代码,再分析:
//链表的快排void QuickSort2(List* pBegin, List* pEnd){ if (pBegin == NULL) return; if (pBegin == pEnd) return; int nTemp; //1. 取第一个元素作为标记元素, 用pSmall指针,指向首元素; int nMark = pBegin->nvalue; List* pSmall = pBegin; //2. 使用pTemp遍历链表 List* pTemp = pBegin->pNext; while (pTemp != pEnd) { //2.1 找到找到小于标记的元素,将pSmall移到下一位置; if (pTemp->nvalue < nMark) { pSmall = pSmall->pNext; //2.2 若下一个位置不是当前位置, 将pSmall 和 pTemp 的元素进行交换; if (pSmall != pTemp) { nTemp = pTemp->nvalue; pTemp->nvalue = pSmall->nvalue; pSmall->nvalue = nTemp; } } pTemp = pTemp->pNext; } //把小链表的最后一个元素和头(标记)交换 //这样pSmall 前就是比nMark小的,后就是比nMark大的; //这块就是把: 16,9,5,15,8,23 --》 8,9,5,15,16,23; nTemp = pSmall->nvalue; pSmall->nvalue = pBegin->nvalue; pBegin->nvalue = nTemp; //while 循环判断,刚好不需要判断最后一个元素,因此就把pSmall 跳过了; QuickSort2(pBegin, pSmall); QuickSort2(pSmall->pNext, pEnd);}int main(){ int arr[] = {16,9,23,5,15,8}; Mylist list; List* pList = list.CreateaaList(arr, sizeof(arr) / 4); list.Print(pList); QuickSort2(pList, NULL); list.Print(pList); system("pause"); return 0;}
解释一下, 递归的参数问题:
在数组的快排中,我们是这样写的,先一次快排,将元素分成两部分, 前部分比标记小,后部分比标记大。返回标记位置,再对 标记的前后两部分进行排序;标记元素已经确定位置,不需要再参加排序了。int nStandard = Sort(arr, nLow, nHigh); QuickSort(arr, nLow, nStandard -1); QuickSort(arr, nStandard+1, nHigh);
在 链表的快排中, 循环判断条件是 pTemp != pEnd, 也就是pEnd 这一位没有进行判断是否加入小链表中。
在函数调用时,我们传入的参数是QuickSort2(pList, NULL);
所以刚好pTemp是从头判断到尾。 进行递归的时候, 传入的pSmall 刚好就不被判断。完成“已经确定位置的标记元素,不需要再参加排序了。” 这一规则。 QuickSort2(pBegin, pSmall); QuickSort2(pSmall->pNext, pEnd);
在开始写的时候, 总想着需要记录pSmall 的前一个元素, 然后递归的时候传 头 — small 前一个, small 后一个—-尾; 这样看似没问题,但是总是跳过元素,然后程序就崩了, 就是没理解好这块。
转载地址:http://nokmi.baihongyu.com/