zoukankan      html  css  js  c++  java
  • 算法之路——插入排序篇1

      本文共有两个关于插入排序的算法,是我自己看书之后的代码实现及自己的理解分析。中间还夹杂着我犯的错误和改正的地方。不当之处,还希望不吝赐教!

    1.直接插入排序
    2.折半插入排序

    (表插入排序将在下一篇文章)

    代码如下:

    /*sort_insertion_sort.h文件*/

    #ifndef sort_insertion_sort
    #define sort_insertion_sort

    #define MAXSIZE 100
    typedef int KeyType;

    typedef struct {
    KeyType data;
    //其他的属性
    }RedType,* PRedType;

    typedef struct {
    RedType list[MAXSIZE];
    int length;
    }SqList, * PSqList;

    #define K_T "%d" //用于输入输出 如 printf(K_T, p->list[i].data);

    #define OK 0
    #define P_NULL 1
    #define TOOBIG 2
    #define NUM_ERROR 3

    int comp(void * d1, void * d2);
    int inputList (PSqList p,int length);
    int outputList (PSqList p);
    int SInsertSort (PSqList p, int (*comp)(void *,void *));
    int BInsertSort (PSqList p, int (*comp)(void *,void *));

    #endif

    /*sort_insertion_sort.cpp文件*/

    //关于插入排序的代码练习,
    #include <stdio.h>
    #include <stdlib.h>
    #include "sort_insertion_sort.h"

    int comp(void * d1, void * d2)
    {//比较函数
    return (((PRedType)d1)->data - ((PRedType)d2)->data );
    }
    int inputList (PSqList p,int length)
    {//输入序列

    if (p == NULL)
    return P_NULL; //1,指针是空的
    if (length > MAXSIZE)
    return TOOBIG; //2,要输入的序列太多

    int i = 0;
    for (i = 0; i < length; i++)
    if (scanf(K_T,&(p->list[i].data)) != 1)
    return NUM_ERROR; //3,输入的数字有误

    p->length = length;
    return OK; //0
    }

    int outputList (PSqList p)
    {//输出序列
    if (p == NULL)
    return P_NULL;

    int i = 0;
    for (i =0; i < p->length; i++)
    printf (K_T"\t",p->list[i].data);
    putchar('\n');
    return OK;
    }//outputList

    int SInsertSort (PSqList p, int (*comp)(void *,void *))
    {
    //直接插入排序
    if (p == NULL)
    return P_NULL;

    RedType tmp;
    int i = 0, j = 0;

    for (i = 1; i < p->length; i++) //i表示将要被插入的下标
    {
    tmp = p->list[i]; //保存第i个数据

    //找到合适的位置
    for (j = i - 1 ; j >= 0 && comp(&(p->list[j]), &tmp) > 0; j--) //#####
    p->list[j+1] = p->list[j];

    p->list[j+1] = tmp; //插入
    }
    return OK;
    }//SInsertSort



    int BInsertSort (PSqList p, int (*comp)(void *,void *))
    {
    if (p == NULL)
    return P_NULL;

    //折半插入排序
    RedType tmp;
    int low, high, i, j;
    low = high = 0;
    i = 0;
    int status; //记录每次比较的结果
    for (i = 1; i < p->length; i++)
    {
    if (comp(&(p->list[i]),&(p->list[i-1])) < 0) //!!!!
    {
    tmp = p->list[i];
    low = 0;
    high = i - 1;
    while (low <= high) //原来:while (low < high)
    {
    status = comp (&(p->list[i]), &(p->list[(low+high)/2]));
    if ( status == 0)
    {
    high = (low+high)/2; //用high记录要插入的位置
    break;
    }//if
    else
    {
    if (status < 0)
    high = (low+high)/2 - 1;
    else
    low = (low + high)/2 +1;
    }//else
    }//while

    // if (comp (&(p->list[i]), &(p->list[high])) < 0) // @@@@@
    // high--;

    for (j = i-1; j > high; j--)
    p->list[j+1] = p->list[j];
    p->list[high+1] = tmp;
    }
    }
    return OK;
    }//BInsertSort

    //以下是我这次写代码是出现的问题的总结和决绝方法。

    /*
    1. ####处的“comp(&(p->list[j]), &tmp)”;只能是tmp。我之前写的是“comp(&(p->list[j]), &(p->list[i]))”是不可以的,虽然tmp是由
    p->list[i]赋值而来,可是p->list[i]随着while()的进行很可能会被p->list[i-1]覆盖,就会出错。所以只能用tmp。

    2. 二分法里,最后当low == high时,还不能确定第i个元素改插入的位置,因为不能确定第high个元素与第i个元素的大小关系,所以需要@@@@
    处的判断,如果第i个元素比第high个元素小,就把high减小1,之后可以确定第i个元素钙放的位置,才是自减过后的high+1的位置。
    不过,如果在while循环里加上个"="的话,出来的high位置的值一定是小于或等于第i个元素的位置,并且第二个元素也会放在正确的位置,
    所以这个解决方法更好


    3.(while(low < high)的情况,没有“=”)还要注意:当在插入第二个元素时,如果仅仅只有二分法的循环是判断不出来第二个元素的位置的,因为low = 0;high = i - 1;之后low==high==0
    不会进入循环的。因此第一个元素和第二个元素的大小关系不知道。所以需要!!!!处的判断,而且该判断还有个好处,不需要的移动的元素不会进入二分
    查找
    */

    /*这是main.cpp文件*/
    #include <stdio.h>
    #include <stdlib.h>
    #include "sort_insertion_sort.h"
    int main (int argc, char * argv)
    {
    int status;
    PSqList test;
    test = (PSqList)malloc(sizeof(SqList));
    int n = 0 ;
    printf("请输入第一组待排序的数的个数(输入0结束循环):");

    while (1)
    {
    while (scanf("%d",&n) != 1)
    {
    puts("输入有误!请重新输入!");
    while(getchar() != '\n');
    }

    if (n == 0) //结束
    break;
    if (status = inputList(test, n) != 0)
    {
    puts("输入的数字有误!");
    while(getchar() != '\n');
    //exit(status);
    }
    //BInsertSort (test,comp);
    SInsertSort (test,comp);
    outputList (test);
    printf("请输入下一组待排序的数的个数(输入0结束循环):");
    }
    free(test);
    return 0;
    }



  • 相关阅读:
    HTTP协议及其POST与GET操作差异 & C#中如何使用POST、GET等
    php中0," ",null和false的区别
    php 上传大文件主要涉及配置upload_max_filesize和post_max_size两个选项。
    php 解决上传中文文件名时出现乱码的问题
    php学习之有用的资源 总结
    php 问题及原因总结
    php 汉字验证码
    php 图片验证码
    php 字母和数字验证码
    php 使用imagettftext()函数出问题的原因
  • 原文地址:https://www.cnblogs.com/svking/p/svking.html
Copyright © 2011-2022 走看看