python/C_快速排序(randomize_quick_sort())

python版(随机化&置换排序版replacement order)

'''
Description:
Version: 2.0
Author: xuchaoxin
Date: 2021-03-26 21:00:45
LastEditors: xuchaoxin
LastEditTime: 2021-03-27 19:49:00
'''
import generate_randomInt
import random
""" partition:we need the state that meet the condition:elements in the left part <= pivot_element;and elements in the right part >=pivot_element;the pivot_element is in the proper location of the sequence finally
it's no more than to describe the demand of the function to achieve a certain algorithm!!
unless you are very familiar to what you write (otherwise ,don't overestimate the degree your understand of the algorithm you are writing;it's time for you to formulate a series of regularity/norm
"""
def partition(dataList, pivot_index): # district
"""这个函数只是为了让quick_sort()内部代码结构更紧凑而提取出来的(不是必须的)
Args:
dataList (list): [description]
pivot_index (Number): [description]
rightList (List): [description]
leftList (List): [description]
"""
size_of_dataList = len(dataList)
""" set two index variable to partition the sequence """
i = 0
j = size_of_dataList-1
""" save the pivot_element to be compared: """
pivot_element = dataList[pivot_index]
""" swap the pivot generated randomly,transform the familiar problem to solve """
dataList[pivot_index], dataList[0] = dataList[0], dataList[pivot_index]
# print("debug...\n pivot_element", pivot_element)
while (i < j):
while(i < j and dataList[j] >= pivot_element):
j -= 1
if i < j:
dataList[i] = dataList[j]
i += 1
while (i < j and dataList[i] < pivot_element):
i += 1
if i < j:
dataList[j] = dataList[i]
j -= 1
# pivot_index=dataList.index(pivot_element)
# if(i < j):
# dataList[i] = dataList[j]
# i+=1
# if(i < j):
# dataList[j] = dataList[i]
# j -= 1
""" the swap operation may not appropriate in the partition process """
# dataList[i],dataList[j]=dataList[j],dataList[i]
""" the pivot insert to the proper place finally """
dataList[i] = pivot_element
# print(dataList)#debug...
""" update the pivot_index after the pass of the partition """
pivot_index = j
""" return to make divide to conquer subproblem """
return pivot_index
def quick_sort(dataList):
"""利用递归来实现快速排序(随机轴心+置换版)
<<<
Args:
dataList (list): 待排序的数列
Returns:
list: 排好序的数列!!!>>>
"""
if len(dataList) >= 2: # 递归入口及出口(如果(当前深度)传入的列表中只有一个元素,则直接返回结果)
""" 选取基准值,也可以选取第一个或最后一个元素(注意这里用地板除法)
这个基准值将要特地取出来,会用来连接左侧序列和右侧序列(也作为关节元素)
"""
pivot_index = random.randint(0, len(dataList)-1)
pivot_element = dataList[pivot_index]
# debug...
# pivot_index = dataList[len(dataList)//2]
# pivot_index = len(dataList)//2
# print("random_pivot_index=", pivot_index)
# print("random_pivot_element=", pivot_element)
""" 逐个判断数列中的各个元素和基准值的大小关系,并放到对应侧的子序列中
可以考虑封装到一个函数中去"""
pivot_index = partition(dataList, pivot_index) # 核心算法(代码段)1
leftList, rightList = dataList[0:pivot_index], dataList[pivot_index+1:]
pivot_element = dataList[pivot_index]
# print("debuging..\n\nleftList:", leftList)
# print("pivot_element:", pivot_element)
# print("rightList:\n", rightList)
""" 递归调用:对两侧子序列分别调用quick_sort()处理 """
return quick_sort(leftList) + [pivot_element] + quick_sort(rightList) # 核心算法(代码段)2
# return leftList+pivot_element+rightList
else:
return dataList
# 示例:
# array = [2, 3,6,6]
# array= [2,3,5,7,1,4,6,15,5,12]
# array = [2, 3, 5, 7, 1, 4, 6, 15, 5, 2, 7, 9, 10, 15, 9, 17, 12]
# array=[5,3,4,2,1,9,]
array = generate_randomInt.generate()
print("the input sequence:\n",array)
print("the sorted sequence:")
print(quick_sort(array))

partition:(good idea adapt from introduction to algorithm)

def partition(dataList, pivot_index): # district
"""这个函数只是为了让quick_sort()内部代码结构更紧凑而提取出来的(不是必须的)
Args:
dataList (list): [description]
pivot_index (Number): [description]
rightList (List): [description]
leftList (List): [description]
"""
size_of_dataList = len(dataList)
""" set two index variable to partition the sequence """
i = 0
j = size_of_dataList-1
""" save the pivot_element to be compared: """
pivot_element = dataList[pivot_index]
""" swap the pivot generated randomly,transform the familiar problem to solve """
dataList[pivot_index], dataList[0] = dataList[0], dataList[pivot_index]
# print("debug...\n pivot_element", pivot_element)
"""
sequence_k:contains the elements<=pivot;
sequence_j:contains the elements>pivot;
k,j grow in two threads (we can know ,all of them grow continuosly separately)
"""
k = 0
for j in range(1, size_of_dataList):
if dataList[j] <= pivot_element:
k += 1
dataList[k], dataList[j] = dataList[j], dataList[k]
""" insert(swap to) the pivot_element to proper location """
dataList[k],dataList[0]=dataList[0],dataList[k]
""" update the pivot_index: """
pivot_index = k
return pivot_index

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

python版2(非随机化&非置换版)

'''
Description:
Version: 2.0
Author: xuchaoxin
Date: 2021-03-07 17:06:52
LastEditors: xuchaoxin
LastEditTime: 2021-03-07 17:54:19
'''
# import generate_randomInt
def divide_zone(dataList, midElement, rightList, leftList): # district
"""这个函数只是为了让quick_sort()内部代码结构更紧凑而提取出来的(不是必须的)
Args:
dataList (list): [description]
midElement (Number): [description]
rightList (List): [description]
leftList (List): [description]
"""
for num in dataList:
# 大于基准值,则放到右侧序列区
if num >= midElement:
rightList.append(num)
else:
leftList.append(num)
def quick_sort(dataList):
"""利用递归来实现快速排序
是一种用空间换时间的方法(类似于归并法,快速法更简单些)
<<<!!!(定义好返回内容(功能)后,再开始递归函数的实现(具体编写依赖于我们对需求的清晰描述)
(先预设定义好功能,哪怕实现不了再回头调整,否则那一进行下去,毕竟递归函数内部要用到调用自己,函数的功能(特别是返回/计算结果)是什么样的很有必要明确)
Args:
dataList (list): 待排序的数列
Returns:
list: 排好序的数列!!!>>>
"""
if len(dataList) >= 2: # 递归入口及出口(如果(当前深度)传入的列表中只有一个元素,则直接返回结果)
""" 选取基准值,也可以选取第一个或最后一个元素(注意这里用地板除法)
这个基准值将要特地取出来,会用来连接左侧序列和右侧序列(也作为关节元素)
"""
midElement = dataList[len(dataList)//2]
""" # 定义基准值左右两侧的列表;随着递归的深入,leftList和rightList区可分配到的元素越来越少(问题规模不断降低)
对于不超过三个元素的某个序列certainList为参数的quick_sort(),"""
leftList, rightList = [], []
dataList.remove(midElement) # 从原始数组中移除被选定为基准值的元素
""" 逐个判断数列中的各个元素和基准值的大小关系,并放到对应侧的子序列中
可以考虑封装到一个函数中去"""
divide_zone(dataList, midElement, rightList, leftList)#核心算法(代码段)1
""" 递归调用:对两侧子序列分别调用quick_sort()处理 """
return quick_sort(leftList) + [midElement] + quick_sort(rightList)#核心算法(代码段)2
else:
return dataList
# 示例:
array = [2,3,5,7,1,4,6,15,5,2,7,9,10,15,9,17,12]
#array = generate_randomInt.generate()
print(quick_sort(array))

C版

/*
* @Description:
* @Version: 2.0
* @Author: xuchaoxin
* @Date: 2021-03-27 18:34:10
* @LastEditors: xuchaoxin
* @LastEditTime: 2021-03-27 19:18:11
*/
#include <stdio.h>
void quick_sort(int s[], int l, int r)
{
if (l < r)
{
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
int i = l, j = r, x = s[l];
while (i < j)
{
/* 在处理和轴心相等的元素时需要注意,由于我们需要知道排序后轴心的索引,(我们以轴心左边的元素都小于轴心为划分目标)
我们包小于轴心的数调到轴心前面,把大等于轴心的元素调到轴心后面(但实际上,轴心在该趟排序完成之前,尚未归位正确的最终位置上),更确切地说,是将严格小于pivot的元素向前调,将大等于pivot的元素向后调,最终会空出一个位置,将pivot插入其中即可(可以用一个比较的简单,而且理性的情况下进行稍微的演算即可知道大概的可行性和正确性)
如果取的轴心不是序列的首元素,那么可以将位于非首元素的轴心和首元素进行调换,从而将问题转换为以首元素为pivot的quickSort
这种情况下,将首元素保存起来(到x) */
while (i < j && s[j] >= x) // 从右向左找第一个小于x的数
j--;
if (i < j)
{ // printf("i=%d ",i);
// printf("s[i]=%d \n",s[i]);
// i++;
s[i] = s[j];
i++;
// printf("i=%d",i);
// printf("s[i++]=%d\n",s[])
}
while (i < j && s[i] < x) // 从左向右找第一个大于等于x的数
i++;
if (i < j)
/* 这时,s[j]会被覆盖,但是在被覆盖之前,s[j]已经安全转移了(就在前面,s[i]=s[j]处) */
s[j--] = s[i];
}
s[i] = x;
quick_sort(s, l, i - 1); // 递归调用
quick_sort(s, i + 1, r);
}
}
int main()
{
// int s[]={ 2,3,5,7,1,4,6,15,5,2,7,9,10,15,9,17,12};
int s[] = {5, 4, 6, 7, 7, 1};
int len = sizeof(s) / sizeof(int);
quick_sort(s, 0, len - 1);
for (int i = 0; i < len; i++)
{
printf("%d ", s[i]);
}
}

C语言2

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define ISHEAP 0/*是否从数组位置1开始编制(堆排序)*/
#define EASY 0/*是否先测试简单例子*/
#define Read_From_Keyboard 0/*是否要从键盘输入数据(若是,改为1)*/
#define MAX 100
/*"排序.c"里的源文件里的函数*/
void quickSort(int r[], int n);
/*main.c*/
int read(int* r)/*EOF结束*/
{
#if ISHEAP
int i = 1;
#else
int i = 0;
#endif
while (scanf("%d", &r[i]) != EOF && i < MAX)
{
i++;
}
return i;
}
int main()
{
/*根据要测试的函数/测试例子的简易程度,选择性编译不同的数组数据*/
#if Read_From_Keyboard
//int* r = (int*)malloc(sizeof(int) * MAX);
int r[MAX];
int n = read(r);
#else
#if ISHEAP
int heapr[] = {-99, 19,15,13,1,6,7,0,3,2,4 };
#else
#if EASY
int r[] = { 10,9,8,7,7,5,4,4,2,1 };
int n = 10;
#else
int r[] = { 19,15,13,1,6,7,0,3,15,7 /*2,4*/};
int n = 10;
#endif
#endif
#endif
printf("testing:\n");
quickSort(r, n);
#if (ISHEAP)
for (int i = 1; i <= n; i++) printf("%d ", heapr[i]);
#else
for (int i = 0; i < n; i++) printf("%d ", r[i]);
#endif
//
}

在这里插入图片描述

#define SWAP(x,y,t) {t = x;x = y;y = t;}
void swap(int* a, int* b)
{
int tmp = 0;
tmp = *a;
*a = *b;
*b = tmp;
}
/*为给定范围内的元素序列,返回枢轴元素值,并将枢纽搬到右边界*/
int median3(int r[], int left, int right)
{
/**********************************************************
通过 三数中值分割法 选取待排序元素r[left ~ right]的枢纽
*********************************************************/
int center = (left + right) / 2,/*中间索引*/
pivot;
/*不难知道,中间值元素的所映无非就是left/center/right*/
/*若三个索引上的元素满足:大中小/小中大*/
if (r[center] <= r[left] && r[center] >= r[right] ||
r[center] >= r[left] && r[center] <= r[right])
pivot = center;/*center对应的元素就是中间值*/
/*若三个索引上的元素满足:中大小/中小大*/
else if (r[left] <= r[center] && r[left] >= r[right] ||
r[left] >= r[center] && r[left] <= r[right])
pivot = left;
/*若三个索引上的元素满足:小大中/大小中*/
else pivot = right;
/*已求得合适的枢轴元素(的索引位置piovt)*/
/* 把枢纽元素放置在尾部(?):为了方便安排从哪一侧先开始收缩边界*/
if (pivot != right)
swap(&r[pivot], &r[right]);
return r[right];/*返回枢轴元素值*/
}
/*主要的排序算法:对数组r[]中下标在[left, right]之间的数据进行快速排序*/
void quickSortImplement(int r[], int left, int right)/*implement:执行*/
{
int pivot_index;
int saveLeft = left,
saveRight = right;
/*递归出口*/
if (left < right)
{
int pivot = median3(r, left, right); //三数中值分割法 选取枢纽元(元素值而非位置)
// 根据枢纽元,把待排序元素分割成前后两部分,且算出枢轴位置,并分别对前后两部分进行快速排序
/*对序列分区(交换调整元素),并求出枢轴的位置保存在pivot_index中*/
int tmp = 0;
//双重双线循环(双线交换):
while (left < right)
{
/*根据枢轴元素所在位置的不同,不能够将while()a 和while()b 的代码顺序对调!(yin'gai)应该将枢轴的对面侧安排在前!
因为如果从枢轴的同一侧开始调整,那枢轴所在的位子就不会被移动(指针直接就扫过它);而从另一侧开始,那枢轴就可以被调整到(正确的中间位置)*/
/*左边界收缩的理想情况*/
while (left < right && r[left] <= pivot)
{
left++;/*先后推++*/
}//while():b
SWAP(r[left], r[right], tmp);//带参宏
/*右边界收缩的理想情况*/
while (left < right && r[right] >= pivot)/*取等号时还不需(不必)要交换,继续测试下一个边界,提高稳定性*/
{
right--;/*往前进--*/
}//while():a
SWAP(r[left], r[right], tmp);//带参宏
}//while;到此为止,可以完成一次分区(与交换元素)的工作
pivot_index = left;/*记录枢轴元的索引位置,此时left = right ;以便后面的递归调用*/
/*递归:*/
/*递归出口:*/
/*递归调用分区交换的功能模块while();使得该函数能够实现全局的快速排序.*/
quickSortImplement(r, saveLeft, pivot_index - 1);/*pivot_index - 1*/
/*after left side have accomplished,then start the right side */
quickSortImplement(r, pivot_index + 1, saveRight);/*pivot_index + 1*/
}//if
}//quickSortImplement()
/*该函数不是必须(唯一的一点儿作用就是减少一个参数(整合两个参数))
对数组r[]中的n个元素进行快速排序;参数为待排序列+元素个数*/
void quickSort(int r[], int n)
{
/*测试数组:建议先用小规模的连续数组:5,4,3,2,1或其它连续值来初步调试基本错误.
调试的基本原则是:先简单(已于看出错误(如果有的话),更进一步才是更一般,更***钻的测试数据(如果连简单数据都过不了,那如和过得了复杂数据呢)*/
//int r[] = { /*90,80,70,*/60,50,40,30,20,10 };int n = 6;
//int r[] = { 19,15,13,1,6,7,0,3,2,4 }; int n = 10;
quickSortImplement(r, 0, n - 1); // 快速排序的具体实现(编写复合函数原型时,以传入实参的方式调用(复合函数的)内存函数)
}
posted @   xuchaoxin1375  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2022-03-08 windows上命令行@文件内容查看方案@行号显示@nlps@cat -n
点击右上角即可分享
微信分享提示