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 @ 2023-03-08 11:46  xuchaoxin1375  阅读(13)  评论(0)    收藏  举报  来源