排序之快速排序(原理、时间复杂度、代码)

一、准备部分

1.数据存储结构:

#define MAXSIZE 1024
typedef  int  KeyType;

typedef struct {
	KeyType key;
}RcdType;

typedef struct {
	RcdType r[MAXSIZE + 1];
	int length;
}Sqlist;

2.基本操作

包括对数据表的初始化、打印和排序时的元素交换,代码如下。

//数据结构打印
void print(Sqlist* list) {
	for (int i = 1; i < list->length; i++) {
		printf("%d ", list->r[i].key);
	}
	printf("%d\n", list->r[list->length].key);
}

//初始化数据存储结构
void initSqlist(Sqlist* list) {
	int i = 0;
	printf("请输入需要排序数据的个数:\n");
	scanf("%d", &list->length);
	printf("请依次输入数据:\n");
	for (i = 1; i <= list->length; i++) {
		scanf("%d", &list->r[i].key);
	}
	return;
}

//排序中的位置交换
void swap(RcdType *a, RcdType *b) {
	RcdType temp = *a;
	*a = *b;
	*b = temp;
	return;
}

二、排序算法

1.快速排序

            快速排序的思想实质上就是将待排序的元素逐个归位。就比如一群不同身高的人站队,A站在第一位,他的身高第5高,那么就让班长1从队尾开始找比A高的人,找到以后,再让班长2从A的后一位开始找比A矮的人,将两人的位置调换。班长2不动,班长1接着找比高的人,找到以后不动,班长2接着找比A矮的人,找到后将两人位置调换……直到班长1与班长2相遇,让A与两位班长对应位置的人交换位置。这样就以A为界限,A前面全是比A高的人,A后面全是比A矮的人。你可能会问了:1.为什么是班长1先找,班长2后找?2.班长1、2相遇时对应位置的人一定不比A矮吗?

       主要考虑相遇时出现的问题。我们发现相遇时无非是两种情况,班长1遇到不动的班长2或者班长2遇到不动的班长1。班长1先找:如果是班长1遇到不动的班长2时,他们所对应的数要么是这个数本身,要么是之前找到的比这个数大的数,把他与第一个数换没有问题。如果是班长2遇到不动的班长1时,班长1因为先动,指向的数一定比当前数大,所以也符合题意。班长2先找不和题意,留给大家自己分析。

       对于算法的时间复杂度,第一次遍历整个链表n次,(假设每次相遇都在正中间)第二次遍历分别遍历n/2、n/2,第三次遍历fenbie遍历n/4、n/4、n/4、n/4……最后遍历到n/n为止,设一共遍历整个list m次,2的m次幂 = n,m = log2n ,所以时间复杂度为:m*n = nlog2n

代码如下:

void quickSort(Sqlist *list, int head, int tail) {
	int i, j;
	if (head >= tail)
		return;
	RcdType temp = list->r[head], t;
	i = head;
	j = tail;
	while (i < j) {
		while (list->r[j].key >= temp.key && i < j)
			j--;
		while (list->r[i].key <= temp.key && i < j)
			i++;
		if (i < j) {
			swap(&list->r[i], &list->r[j]);
		}
	}
	list->r[head] = list->r[i];
	list->r[i] = temp;
	quickSort(list, head, i - 1);
	quickSort(list, i + 1, tail);
	return;
}
void swap(RcdType *a, RcdType *b) {
	RcdType temp = *a;
	*a = *b;
	*b = temp;
	return;
}

补充了一段java版本的快速排序

import java.util.Random;

public class quick_sort {
    public static void main(String[] args) {
        int []arr = new int[]{5,6,9,8,2,3};
        quickS(arr,0,arr.length-1);
        for(int i = 0; i < arr.length; i++){
            System.out.print(arr[i] + " ");
        }
    }
    public static void quickS(int []arr,int begin,int end){
        if(begin == end || end - begin < 2)
            return ;
        int left = begin;
        int right  = end;
        Random random = new Random();
        int ran = random.nextInt(end - begin) + begin;
        int baseValue = arr[ran];
        swap(arr,ran,end);
        int i  = 0;
        while(i < right){
            if(arr[i] < baseValue){
                swap(arr,i,left);
                i++;
                left++;
            }
            else if(arr[i] ==baseValue){
                i++;
            }
            else {
                right--;
                swap(arr,i,right);
            }
        }
        swap(arr,end,right);
        quickS(arr,begin,left);
        quickS(arr,right+1,end);
    }

    public static void swap(int []arr,int childIndex, int parentIndex){
        int a;
        a = arr[childIndex];
        arr[childIndex] = arr[parentIndex];
        arr[parentIndex] = a;
    }
}

排序的时间复杂度:O(n*logn)

空间复杂度:O(logn)  ->递归过程浪费的空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值