【问题标题】:Best way to combine insertionSort and mergeSort?结合插入排序和合并排序的最佳方法?
【发布时间】:2021-09-27 13:44:29
【问题描述】:

我正在研究一种算法,它结合了 mergeSort 和 insertionSort 的优点。众所周知,对于小于 43.559 或大约 44 的问题大小,insertionSort 比 mergeSort 快。我正在尝试在 C 中实现这一点,但收到了一些错误。数组正在部分排序,并且某些值正在重复。我已经单独测试了mergeSort,它可以完美运行。我的代码和输出如下:

#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#define FILE1 "../data/data.txt"

void processFile(void);
int *createBuffer(int count);
int getBufferSize(void);
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void insert(int *, int);
void insertionSortRecursive(int *, int);
void print(int *, int);

int main() {
  processFile();
  int bufferSize = getBufferSize();
  printf("%d <<<<", bufferSize);
  int *buffer = createBuffer(bufferSize);
  mergeSort(buffer, bufferSize);
  print(buffer, bufferSize);
}

void processFile(void) {
  FILE *file = fopen(FILE1, "r+");
  int ch;

  int replacement = ' ';
  int delimiter = ',';
  while (1) {

    ch = fgetc(file);
    if (ch == EOF) {
      break;
    }
    if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') {
      fseek(file, ftell(file) - 1, SEEK_SET);
      fprintf(file, "%c", replacement);
    } else if (ch == ' ' || ch == '\n') {
      fseek(file, ftell(file) - 1, SEEK_SET);
      fprintf(file, "%c", delimiter);
    } else if (ch == ',') {
    }
  }
  fclose(file);
}

int getBufferSize(void) {
  FILE *file = fopen(FILE1, "r");
  int count = 0;
  int ch;
  while (1) {
    ch = fgetc(file);
    if (ch == EOF) {
      break;
    } else if (ch == ',') {
      ++count;
    }
  }
  int bufferSize = count + 1;
  fclose(file);
  return bufferSize;
}

int *createBuffer(int count) {
  FILE *file = fopen(FILE1, "r");
  int *buffer = (int *)malloc(sizeof(int) * (count + 1));
  int ch;
  int number;
  int i = 0;
  while (1) {
    ch = fgetc(file);
    if (ch == EOF) {
      break;
    }
    if (fscanf(file, "%i", &number) == 1) {
      buffer[i] = number;
      ++i;
    }
  }
  fclose(file);
  return buffer;
}

void mergeSort(int *A, int arraySize) {
  if (arraySize < 44) {
    return insertionSortRecursive(A, arraySize);
  }
  int mid = arraySize / 2;
  int L[mid];
  int R[arraySize - mid];
  for (int i = 0; i < mid; i++) {
    L[i] = A[i];
  }
  for (int j = mid; j < arraySize; j++) {
    R[j - mid] = A[j];
  }
  mergeSort(L, mid);
  mergeSort(R, arraySize - mid);
  merge(A, L, mid, R, arraySize - mid);
}

void merge(int *A, int *L, int leftSize, int *R, int rightSize) {
  int i = 0, j = 0, k = 0;
  while (i < leftSize && j < rightSize) {
    if (L[i] < R[j]) {
      A[k] = L[i];
      i++;
      k++;
    } else {
      A[k] = R[j];
      j++;
      k++;
    }
  }
  while (i < leftSize) {
    A[k] = L[i];
    i++;
    k++;
  }
  while (j < rightSize) {
    A[k] = R[j];
    j++;
    k++;
  }
}

void insert(int *A, int k) {
  int key = A[k];
  int index = k - 1;
  while (index >= 0 && A[index] > key) {
    A[index + 1] = A[index];
    index--;
  }
  A[index + 1] = key;
}

void insertionSortRecursive(int *A, int k) {
  if (k > 1) {
    insertionSortRecursive(A, k - 1);
    insert(A, k);
  }
}

void print(int *buffer, int bufferSize) {
  for (int i = 0; i < bufferSize; i++) {
    printf("%d ", buffer[i]);
  }
}

显然,我不希望您仔细阅读输出。 (因为实际上是对 1000 个随机数进行排序),但我希望您注意两件事: 首先,在有缺陷的输出中,1 在输出的开头重复了几次,在输出的结尾,最终的数字是 929。这意味着正在发生部分排序,但我不确定为什么我会开始时得到一堆 1。

输出(仅使用 mergeSort)

1 2 3 5 5 7 7 7 8 8 9 9 12 12 14 14 15 15 16 16 17 18 18 19 19 21 23 24 24 24 24 26 27 27 30 30 31 32 32 34 34 35 35 37 37 38 38 39 40 42 42 43 44 46 47 48 49 50 50 52 52 52 53 53 54 55 56 56 58 58 62 62 63 68 71 72 75 76 76 77 78 79 79 80 82 82 83 87 91 94 96 96 100 100 101 102 103 105 106 108 108 111 113 114 115 115 118 119 120 121 121 124 126 130 130 130 132 132 133 133 134 134 134 135 135 137 137 139 141 141 146 147 148 149 151 152 154 156 156 157 158 158 162 163 164 164 165 166 166 167 169 169 171 172 172 172 175 176 176 177 179 180 183 184 184 185 185 187 188 188 189 189 189 190 196 198 199 200 200 201 203 203 203 204 204 204 205 205 206 206 207 207 208 211 211 211 212 213 214 215 215 215 217 218 219 220 220 221 222 223 225 225 226 226 226 228 228 228 229 229 229 230 230 230 233 233 233 234 235 238 238 239 239 240 242 244 244 246 246 249 251 253 254 256 256 256 257 258 258 258 259 262 263 265 266 266 267 267 268 269 271 271 271 272 275 277 279 279 281 281 282 282 283 284 284 285 285 288 288 292 293 293 295 295 296 297 298 298 300 300 302 303 306 306 309 309 313 313 314 314 315 316 317 319 320 321 322 323 323 325 326 329 329 333 333 334 334 334 334 336 336 337 337 339 340 340 341 342 342 342 342 344 344 344 347 349 349 351 353 354 354 355 356 356 358 359 360 360 361 362 364 364 366 366 367 368 368 370 370 371 372 372 373 376 376 376 376 379 381 381 381 381 382 382 382 383 384 385 387 388 391 393 395 396 396 397 397 397 398 399 399 399 399 400 401 402 408 411 412 412 414 415 415 416 418 418 419 423 423 425 426 426 426 427 429 429 429 430 430 433 433 433 434 436 437 437 437 437 439 439 439 439 440 441 441 441 444 444 444 445 446 447 447 448 449 449 450 451 453 454 457 459 459 459 460 460 461 463 465 466 468 469 470 472 472 472 472 472 473 473 474 474 477 477 478 480 480 480 481 482 482 482 483 483 484 484 485 486 486 487 487 488 489 490 491 492 492 493 493 495 497 497 497 497 499 499 500 502 502 503 503 504 505 506 507 507 508 509 509 511 511 512 513 514 514 515 515 515 516 517 518 520 520 521 522 523 523 524 525 525 525 527 529 529 531 531 533 534 535 535 535 535 536 536 536 538 539 539 540 541 543 544 544 545 546 547 548 549 550 551 552 554 555 555 557 558 559 559 559 559 560 563 564 564 564 565 565 565 567 568 569 570 571 571 573 574 574 576 581 583 584 586 586 587 589 590 591 592 594 594 595 595 596 596 597 598 603 604 604 606 606 607 607 609 611 611 612 613 613 614 614 614 614 615 615 617 617 617 618 621 624 624 626 628 628 632 632 634 637 638 639 640 640 640 643 644 644 645 646 649 651 651 652 653 654 655 655 658 660 660 661 661 663 664 665 665 666 667 667 667 667 668 668 673 674 674 674 676 678 678 679 679 679 683 684 686 687 689 691 692 693 693 694 694 695 695 696 697 698 701 702 702 703 703 704 704 706 706 707 707 709 709 711 712 713 714 717 718 718 718 718 721 721 722 723 725 725 725 726 727 729 730 730 730 730 732 735 735 736 738 739 739 740 740 743 744 747 749 749 749 749 749 750 750 751 752 752 753 755 756 756 757 759 759 760 761 761 763 763 764 766 767 769 771 772 775 775 775 775 775 776 776 777 777 777 779 780 781 781 783 784 784 785 786 786 787 788 788 791 792 792 792 795 796 799 799 799 799 800 800 800 800 800 801 804 805 807 808 813 813 817 823 824 825 825 828 829 829 829 830 830 832 833 836 837 839 839 840 840 842 843 845 846 848 850 850 850 850 850 857 858 862 862 863 863 864 865 865 867 867 868 868 869 869 870 870 870 871 871 872 874 876 876 882 883 883 883 883 884 886 886 888 888 890 890 892 892 894 895 895 898 898 899 902 902 903 906 907 910 912 912 914 914 916 916 917 919 920 920 920 921 921 922 923 925 928 929 930 930 930 932 933 934 935 935 935 936 941 943 943 946 947 949 949 950 950 951 951 952 952 953 953 954 954 955 955 957 959 962 963 966 968 969 969 970 970 970 972 972 974 975 976 977 977 977 977 978 979 980 981 983 984 986 987 987 988 990 991 991 992 993 994 996 996 997 997 997 998 999 999 %   

输出(带组合):

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 7 7 8 9 9 12 12 14 14 16 18 18 19 19 23 24 24 24 26 27 27 30 30 31 34 35 37 37 42 42 46 48 49 50 50 52 52 53 53 54 56 58 62 24 39 55 56 62 63 68 71 72 76 79 79 83 87 94 96 100 101 103 106 108 113 119 120 121 121 130 130 132 133 133 134 135 135 137 139 141 141 147 148 149 151 154 156 156 158 158 163 164 166 167 169 172 175 176 176 177 179 180 183 184 185 187 189 189 190 196 198 199 200 201 203 203 204 205 206 206 207 207 208 211 211 212 213 214 215 215 217 220 220 221 222 223 225 225 226 226 228 228 229 229 230 230 233 233 234 238 239 239 240 244 246 246 251 253 256 258 258 259 263 266 267 267 268 269 271 272 275 277 279 279 281 281 282 282 283 284 284 285 285 292 295 296 297 298 298 300 300 302 306 309 313 313 314 317 319 323 325 326 334 334 336 337 339 340 342 342 342 344 344 344 351 354 355 356 358 364 366 366 367 370 372 372 373 376 376 376 379 381 381 382 383 384 396 396 397 397 399 399 399 400 401 402 408 412 412 414 415 415 418 418 423 425 426 427 429 360 368 426 434 436 437 437 439 439 439 440 441 441 444 444 444 446 449 450 451 453 454 457 459 459 459 460 460 461 43 82 134 152 188 203 244 257 295 323 360 364 397 433 447 463 465 469 472 472 472 472 474 474 477 478 480 480 480 481 482 483 485 486 487 490 495 497 497 497 497 502 502 503 503 507 509 511 514 516 518 520 520 522 523 523 525 525 525 527 529 529 533 535 535 536 539 539 544 545 546 547 551 552 554 555 557 558 559 559 560 564 567 568 570 571 573 574 576 584 589 590 594 594 595 596 597 52 75 80 105 118 137 146 204 226 271 293 508 515 563 603 606 606 611 612 614 614 614 615 617 565 571 607 613 617 624 626 628 637 638 639 640 651 651 652 653 654 660 660 665 666 668 673 674 678 683 684 686 687 691 692 693 694 696 697 698 702 702 703 703 704 704 706 707 707 709 718 718 718 718 722 725 725 726 329 334 337 381 398 429 429 433 441 468 493 550 559 649 689 694 721 729 730 730 735 735 739 740 740 744 749 749 749 750 750 752 753 755 756 757 759 759 760 761 763 764 766 767 769 771 569 604 611 646 667 679 693 738 749 772 775 775 775 775 777 777 779 780 784 787 788 663 664 676 678 786 791 792 792 796 799 800 800 800 800 801 807 808 813 813 817 823 825 828 829 829 829 830 830 832 833 836 839 840 840 842 846 850 850 857 858 863 867 867 482 489 491 493 531 535 541 559 586 613 614 617 655 661 661 706 711 723 785 868 868 870 870 872 874 876 876 882 883 884 886 886 235 262 293 316 349 362 371 419 437 449 466 488 499 509 513 555 586 632 634 730 732 781 869 888 888 890 890 892 898 899 902 902 903 906 907 910 912 914 914 917 8 82 100 115 126 204 288 303 333 334 349 370 385 387 391 423 445 499 517 534 548 665 667 674 721 763 784 795 912 920 922 923 925 928 930 505 512 536 604 624 645 674 727 743 850 883 930 932 934 935 935 935 936 946 947 949 949 950 951 581 609 695 714 747 799 843 845 850 898 952 76 184 205 321 336 359 381 426 430 433 484 487 538 565 621 725 799 824 837 850 862 863 883 894 920 952 953 955 962 963 966 968 16 44 58 78 166 218 229 238 254 271 341 342 382 411 472 482 483 504 514 521 565 596 598 640 701 736 776 786 921 969 969 5 15 17 34 77 114 162 164 185 256 309 322 448 500 506 515 531 536 540 543 549 583 730 749 751 805 862 871 930 950 970 972 974 976 977 5 15 32 111 165 169 172 188 189 200 228 249 354 395 447 473 535 592 655 658 712 713 775 776 800 804 920 953 959 977 2 35 91 132 171 266 314 315 329 333 340 353 361 393 473 492 524 564 628 643 667 668 695 752 761 799 864 865 883 954 978 980 981 986 21 38 96 102 134 219 511 233 256 288 356 368 388 416 470 484 507 515 587 607 615 640 644 679 717 756 777 871 916 943 987 988 991 992 996 999 7 38 47 108 124 130 157 215 230 242 258 306 399 439 477 486 591 595 644 679 739 783 792 839 870 895 941 954 970 979 999 32 40 115 172 211 265 320 781 347 376 382 430 437 492 544 564 574 618 632 667 709 788 825 848 865 869 895 916 921 929

与往常一样,如果您花时间回答或尝试回答这个问题,那么感谢您的宝贵时间。

【问题讨论】:

  • 请提供测试代码/输入。也就是说,main 设置输入和对测试函数的调用。
  • 代码仍然不完整。例如,createBuffer 缺失。见How to create a Minimal, Reproducible Example
  • @kaylum 就是这么做的。谢谢你让我知道。此外,processFile、createBuffer 和 getBufferSize 与排序算法中的代码无关。它们仅用于排序前的文件处理。不过我还是添加了完整的代码。
  • 请看链接。重要的问题通常不能仅仅通过目测来调试。其他人可能需要运行代码来调试并查看它的作用。当然,确切的测试数据也很重要。因此需要完整的代码。
  • @kaylum 很抱歉。 -- 完整代码现已发布。

标签: c algorithm mergesort insertion-sort


【解决方案1】:

为什么不对少量元素(16 到 32)使用传统的插入排序而不是递归插入排序(其余的将是合并排序)?

void InsertionSort(int a[], int ll, int ee)
{
    int i, j;
    int t;
    for (j = ll + 1; j < ee; j++) {
        t = a[j];
        i = j-1;
        while(i >= ll && a[i] > t){
            a[i+1] = a[i];
            i--;
        }
        a[i+1] = t;
    }   
}

混合插入排序和基于指针的自底向上合并排序的旧示例,其中插入排序和合并函数与合并排序代码内联。在我的系统上,这段代码对 1600 万个整数进行排序只需不到 1.5 秒:

size_t GetPassCount(size_t n);

void MergeSort(uint32_t a[], uint32_t b[], size_t n)
{
uint32_t *p0r;                              /* ptr to current element run 0 */
uint32_t *p0e;                              /* ptr to end             run 0 */
uint32_t *p1r;                              /* ptr to current element run 1 */
uint32_t *p1e;                              /* ptr to end             run 1 */
uint32_t *pax;                              /* ptr to a[] or b[] */
uint32_t *pbx;                              /* ptr to b[] or a[] */
size_t rsz;                                 /* run size  */
    if(n < 2)                               /* if size < 2 return */
        return;
    /* set run size so merge sort is even number of passes */
    rsz = ((GetPassCount(n) & 1) != 0) ? 32 : 16;
    {                                       /* insertion sort */
        size_t l, r;
        size_t i, j;
        uint32_t t;
        for (l = 0; l < n; l = r) {
            r = l + rsz;
            if (r > n)r = n;
            l--;
            for (j = l + 2; j < r; j++) {
                t = a[j];
                i = j-1;
                while(i != l && a[i] > t){
                    a[i+1] = a[i];
                    i--;
                }
                a[i+1] = t;
            }
        }
    }

    while(rsz < n){                     /* merge sort */
        pbx = &b[0];
        pax = &a[0];
        while(pax < &a[n]){
            p0e = rsz + (p0r = pax);
            if(p0e >= &a[n]){
                p0e = &a[n];
                goto cpy10;}
            p1e = rsz + (p1r = p0e);
            if(p1e >= &a[n])
                p1e = &a[n];
            /* 2 way merge */
            while(1){
                if(*p0r <= *p1r){
                    *pbx++ = *p0r++;    /* run 0 smallest */
                    if(p0r < p0e)       /* if not end run continue */
                        continue;
                    goto cpy11;
                } else {
                    *pbx++ = *p1r++;    /* run 1 smallest */
                    if(p1r < p1e)       /* if not end run continue */
                        continue;
                    goto cpy10;
                }
            }
cpy11:      p0r = p1r;
            p0e = p1e;
            /* 1 way copy */
cpy10:      while (1) {
                *pbx++ = *p0r++;        /* copy element */
                if (p0r < p0e)          /* if not end of run continue */
                    continue;
                break;
            }
            pax += rsz << 1;            /* setup for next set of runs */
        }
        pax = a;                        /* swap ptrs */
        a = b;
        b = pax;
        rsz <<= 1;                      /* double run size */
    }
}

size_t GetPassCount(size_t n)               /* return # passes */
{
    size_t i = 0;
    for(size_t s = 1; s < n; s <<= 1)
        i += 1;
    return(i);
}

【讨论】:

  • 传统的插入排序比普通的合并排序慢得多——在最坏的情况下 O(n^2) 时间复杂度与 O(nlgn) 相比,组合插入-合并排序结合了两者的最佳方面进一步降低了时间复杂度。这就是我尝试使用该组合的原因。
  • @AnishSinha - 我的意思是对 16 到 32 个元素使用传统的插入排序而不是递归插入排序,其余的将是合并排序。我更新了我的答案以明确这一点。
  • 你可能有一个观点。这肯定会更容易。我一定会试试这个,让你知道!谢谢您的帮助。 (:
  • @AnishSinha - 我更新了我的答案以展示一个非常古老的混合插入 + 合并排序示例,其中合并排序基于指针,并包括 goto 以处理来自多个公共目的地的分支点源位置(而不是重复代码)。
【解决方案2】:

警告:这只是对您的一个问题的部分修复。

在mergeSort的顶部,你需要:

if (arraySize < 2)
    return;

否则,您可以获得无限递归,arraySize 值为 0。

之后,您的归并排序似乎可以工作了。但是,您的插入排序仍然需要做更多的工作。


为了帮助调试,我创建了一个额外的测试夹具。它检查数组是否越界。

它生成随机数组。

至少对于在此处发布 [无法发布大型测试数据文件的地方],数组的动态生成是任何响应者都可以调用的。

这是代码,通过额外的调试/交叉检查进行了重构:

#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#define FILE1 "../data/data.txt"

typedef struct {
    int *arr_base;
    int arr_count;
    int arr_max;
} arr_t;

unsigned int opt_R;
int opt_L;

arr_t test;
arr_t save;
#define MARGIN      16

#ifndef ISORT
#define ISORT   44
#endif

void processFile(void);
int *createBuffer(int count);
int getBufferSize(void);
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void insert(int *, int);
void insertionSortRecursive(int *, int);
void print(int *, int);

#define sysfault(_fmt...) \
    do { \
        printf(_fmt); \
        exit(1); \
    } while (0)

#ifdef DBGCHK
#define dbgchk(_reason) \
    arrchk(_reason)
#else
#define dbgchk(_reason) \
    do { } while (0)
#endif

void
arrdup(arr_t *save,const arr_t *tst)
{

    save->arr_count = tst->arr_count;
    save->arr_max = tst->arr_max;
    save->arr_base = realloc(save->arr_base,sizeof(int) * save->arr_max);

    for (int idx = 0;  idx < save->arr_max;  ++idx)
        save->arr_base[idx] = tst->arr_base[idx];
}

void
arrgen(void)
{
    arr_t *tst = &test;

    printf("R = %u\n",opt_R);

    if (opt_L > 0)
        tst->arr_count = opt_L;
    else
        tst->arr_count = (rand_r(&opt_R) % 100) + 1;
    printf("L = %d\n",tst->arr_count);

    tst->arr_max = MARGIN + tst->arr_count + MARGIN;

    tst->arr_base = realloc(tst->arr_base,sizeof(int) * tst->arr_max);

    int *ptr = tst->arr_base;
    int idx;
    int val = -1;

    for (idx = 0;  idx < MARGIN;  ++idx, --val, ++ptr)
        *ptr = val;

    for (idx = 0;  idx < tst->arr_count;  ++idx, ++ptr)
        *ptr = (rand_r(&opt_R) % tst->arr_count) + 1;

    for (idx = 0;  idx < MARGIN;  ++idx, --val, ++ptr)
        *ptr = val;

    arrdup(&save,tst);
}

void
arrchk(const char *reason)
{
    const arr_t *tst = &test;
    const int *ptr = tst->arr_base;
    int val = -1;
    int idx;

    for (idx = 0;  idx < MARGIN;  ++idx, --val, ++ptr) {
        if (*ptr != val)
            sysfault("arrchk: BEF ptr=%zu EXPECTED:%d ACTUAL:%d (from %s)\n",
                ptr - tst->arr_base,val,*ptr,reason);
    }

    for (idx = 0;  idx < tst->arr_count;  ++idx, ++ptr) {
        if (*ptr < 0)
            sysfault("arrchk: ARR ptr=%zu ACTUAL:%d (from %s)\n",
                ptr - tst->arr_base,*ptr,reason);
    }

    for (idx = 0;  idx < MARGIN;  ++idx, --val, ++ptr) {
        if (*ptr != val)
            sysfault("arrchk: AFT ptr=%zu EXPECTED:%d ACTUAL:%d (from %s)\n",
                ptr - tst->arr_base,val,*ptr,reason);
    }
}

void
srtchk(const char *reason)
{
    arr_t *tst = &test;
    int *ptr = &tst->arr_base[MARGIN];
    int idx;

    arrchk(reason);

    int prev = *ptr++;
    for (idx = 1;  idx < tst->arr_count;  ++idx, ++ptr) {
        if (*ptr < prev)
            sysfault("arrchk: AFT ptr=%zu PREV:%d CUR:%d (from %s)\n",
                ptr - tst->arr_base,prev,*ptr,reason);
        prev = *ptr;
    }
}

int
main()
{
#if 0
    processFile();
    int bufferSize = getBufferSize();

    printf("%d <<<<", bufferSize);
    int *buffer = createBuffer(bufferSize);

    mergeSort(buffer, bufferSize);
    print(buffer, bufferSize);
#else
    arrgen();
    mergeSort(&test.arr_base[MARGIN],test.arr_count);
    srtchk("main");
#endif
}

void
processFile(void)
{
    FILE *file = fopen(FILE1, "r+");
    int ch;

    int replacement = ' ';
    int delimiter = ',';

    while (1) {

        ch = fgetc(file);
        if (ch == EOF) {
            break;
        }
        if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) {
            fseek(file, ftell(file) - 1, SEEK_SET);
            fprintf(file, "%c", replacement);
        }
        else if (ch == ' ' || ch == '\n') {

            fseek(file, ftell(file) - 1, SEEK_SET);
            fprintf(file, "%c", delimiter);

        }
        else if (ch == ',') {
        }
    }
    fclose(file);
}

int
getBufferSize(void)
{
    FILE *file = fopen(FILE1, "r");
    int count = 0;
    int ch;

    while (1) {
        ch = fgetc(file);
        if (ch == EOF) {
            break;
        }
        else if (ch == ',') {
            ++count;
        }
    }
    int bufferSize = count + 1;

    fclose(file);
    return bufferSize;
}

int *
createBuffer(int count)
{
    FILE *file = fopen(FILE1, "r");
    int *buffer = (int *) malloc(sizeof(int) * (count + 1));
    int ch;
    int number;
    int i = 0;

    while (1) {
        ch = fgetc(file);
        if (ch == EOF) {
            break;
        }
        if (fscanf(file, "%i", &number) == 1) {
            buffer[i] = number;
            ++i;
        }
    }
    fclose(file);
    return buffer;
}

void
mergeSort(int *A, int arraySize)
{
// NOTE/BUG: we need to stop or we get infinite recursion with zero count
#if 1
    if (arraySize < 2)
        return;
#endif

    if (arraySize < ISORT)
        return insertionSortRecursive(A, arraySize);

    int mid = arraySize / 2;
    int L[mid];
    int R[arraySize - mid];

    for (int i = 0; i < mid; i++) {
        L[i] = A[i];
    }
    for (int j = mid; j < arraySize; j++) {
        R[j - mid] = A[j];
    }
    mergeSort(L, mid);
    mergeSort(R, arraySize - mid);
    merge(A, L, mid, R, arraySize - mid);
}

void
merge(int *A, int *L, int leftSize, int *R, int rightSize)
{
    int i = 0,
        j = 0,
        k = 0;

    dbgchk("merge/BEF");

    while (i < leftSize && j < rightSize) {
        if (L[i] < R[j]) {
            A[k] = L[i];
            i++;
            k++;
        }
        else {
            A[k] = R[j];
            j++;
            k++;
        }
    }
    while (i < leftSize) {
        A[k] = L[i];
        i++;
        k++;
    }
    while (j < rightSize) {
        A[k] = R[j];
        j++;
        k++;
    }

    dbgchk("merge/AFT");
}

void
insert(int *A, int k)
{
    int key = A[k];
    int index = k - 1;

    while (index >= 0 && A[index] > key) {
        A[index + 1] = A[index];
        index--;
    }
    A[index + 1] = key;
}

void
insertionSortRecursive(int *A, int k)
{
    if (k > 1) {
        insertionSortRecursive(A, k - 1);
        insert(A, k);
    }
}

void
print(int *buffer, int bufferSize)
{
    for (int i = 0; i < bufferSize; i++) {
        printf("%d ", buffer[i]);
    }
}

【讨论】:

    【解决方案3】:

    我的rubber duck 指出insert() 例程似乎期望数组的长度作为它的第二个参数k。但是您将A[k] 元素存储为key,它在要排序的数组之外。

    行:

    int key = A[k];
    

    应改为:

    int key = A[k - 1];
    

    顺便说一句,整个递归是不必要的:

    void insertionSortRecursive(int *A, int k) {
      if (k > 1) {
        insertionSortRecursive(A, k - 1);
        insert(A, k);
      }
    }
    

    也可以迭代完成:

    void insertionSortIterative(int *A, int k) {
      for (int i = 2; i <= k; ++i)
        insert(A, i);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-03
      • 2013-02-25
      相关资源
      最近更新 更多