7-10 指针版本的快速排序

1. 另一种快排的方式,注意枢轴元素的值是拿出来比较的,最后一刻才会确定枢轴元素所在的位置,值和位置需要注意区分

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void SwapInt(int *a, int *b){
  int temp = *a;
  *a = *b;
  *b = temp;
}

void Shuffle(int *array, int length) {
  srand(time(NULL));

  for (int i = length - 1; i > 0; --i) {
    int random_number = rand() % i;
    SwapInt(array + i, array + random_number);
  }
}

// 不用指针的快排,不过是中间枢轴法
int PartitionNormal(int low, int high, int array[]){
  int pivot = array[(low + high)/2];

  int i = low;
  int j = high;

  while(i<j){
    if(array[i] < pivot){
      i++;
    }
    if(array[j] > pivot){
      j--;
    }
    SwapInt(array+i, array+j);
  }

  return i;
}

void QuickSortNormal(int low, int high, int array[]){
  if(low > high)
    return;
  int partition = PartitionNormal(low, high, array);
  QuickSortNormal(low, partition-1,array);
  QuickSortNormal(partition+1, high, array);
}

#define PLAYER_COUNT 20

int main() {
  int *players = malloc(sizeof(int) * PLAYER_COUNT);

  if (!players) {
    return 1;
  }

  for (int i = 0; i < PLAYER_COUNT; ++i) {
    players[i] = i;
  }

  Shuffle(players, PLAYER_COUNT);

  printf("排序前:");
  for (int i = 0; i < PLAYER_COUNT; ++i) {
    printf("%d, ", players[i]);
  }

  QuickSortNormal(0, 19, players);

  printf("\n排序后:");
  for (int i = 0; i < PLAYER_COUNT; ++i) {
    printf("%d, ", players[i]);
  }

  return 0;
}

对了,shuffle 那边有些变化,原先传进去的参数是 int array[],现在变成了 int *array,其实两者是一样的:

2. 指针版本的快排,把数组思想放弃,数组思想转变为一个内存指针的思想,数组的元素的下标和取值就是指针变量的各种运算,不再是对数组元素进行排序,而是对一个内存块进行排序

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void SwapInt(int *a, int *b){
  int temp = *a;
  *a = *b;
  *b = temp;
}

void Shuffle(int array[], int length) {
  // 创建随机种子
  srand(time(NULL));

  for (int i = length-1; i > 0; --i) {
    int random_number = rand() % i;
    SwapInt(array+i, array+random_number);
  }
}

int *PartitionPointer(int *low, int *high){
  int pivot = *(low + (high-low)/2);

  int* i = low;
  int* j = high;

  while(i < j){
    if(*i < pivot){
      i++;
    }
    if(*j > pivot){
      j--;
    }
    SwapInt(i, j);
  }

  return i;
}

void QuickSortPointer(int *low, int *high){
  if(low > high)
    return;
  int *partition = PartitionPointer(low, high);
  QuickSortPointer(low, partition-1);
  QuickSortPointer(partition+1, high);
}

#define PLAYER_COUNT 20

int main() {
  int *players = malloc(sizeof(int) * PLAYER_COUNT);

  if (!players) {
    return 1;
  }

  for (int i = 0; i < PLAYER_COUNT; ++i) {
    players[i] = i;
  }

  Shuffle(players, PLAYER_COUNT);

  printf("排序前:");
  for (int i = 0; i < PLAYER_COUNT; ++i) {
    printf("%d, ", players[i]);
  }

  QuickSortPointer(players, players+PLAYER_COUNT-1);

  printf("\n排序后:");
  for (int i = 0; i < PLAYER_COUNT; ++i) {
    printf("%d, ", players[i]);
  }

  return 0;
}

最后附上老师的代码:

int *Partition(int *low, int *high) {
  int pivot = *(low + (high - low) / 2);
  int *p = low;
  int *q = high;

  while (1) {
    while (*p < pivot) p++;
    while (*q > pivot) q--;

    if (p >= q) break;
    SwapInt(p, q);
  }

  return q;
}

void QuickSort(int *low, int *high) {
  if (low >= high) return;
  int *partition = Partition(low, high);
  QuickSort(low, partition - 1);
  QuickSort(partition + 1, high);
}

提问:

1. 为什么 (low + high)/2 没有 low + (high-low)/2 好,为什么后者可以防止溢出?

    想象一下,如果下标是 98 亿 和 99亿 ,对比计算一下。其实后者并不是绝对防止溢出,而是扩展性更好,把大数计算转变为了小数计算,前者太依赖计算机的精度。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值