• 数据结构学习第八天


    18:35:51 2019-08-23

    学习

     16:55:15 2019-08-24

    补充了 插值查找

     无序向量的操作 以及  有序向量 二分查找  Fibonacci查找

      1 #define _CRT_SECURE_NO_WARNINGS    //vs中scanf为不安全的函数 要使用 得加上这句话
      2 #include<stdio.h>
      3 #define Size 10
      4 int Vector[10] = { 1,6,8,9,11,15,18,33,40,61 };
      5 //int Vector[Size];
      6 // 无序向量
      7 int GetElement(int Rank)  //按秩访问元素 
      8 {
      9     if (Rank < Size)
     10         return Vector[Rank];
     11     else
     12         return -1;
     13 }
     14 void Insert(int Rank, int Element) //按秩插入元素
     15 {
     16     if (Rank < Size)
     17     {
     18         for (int i = Size - 1; i >Rank; i--)
     19         {
     20             Vector[i] = Vector[i - 1];
     21         }
     22         Vector[Rank] = Element;
     23     }
     24 }
     25 int Delete(int lo, int hi)  //区间删除 单元素删除时区间删除的特列
     26 {
     27     for (;hi< Size;)
     28         Vector[lo++] = Vector[hi++];
     29     return hi - lo;
     30 }
     31 int Find(int Element,int lo,int hi)  //在范围中查找元素
     32 {
     33     while (lo<hi-- && Vector[hi] != Element);
     34     return hi;
     35 } 
     36 int  DeleteOne(int Rank)   //单元素删除
     37 {
     38     Delete(Rank, Rank + 1);
     39     return Vector[Rank];
     40 }
     41 void DeDuplicate() //无序向量的唯一化   低效版
     42 {
     43     int i = 0;
     44     while (i<Size)
     45     {
     46         Find(Vector[i], 0, i) > 0 ? DeleteOne(i) : i++;
     47     }
     48 }
     49 
     50 
     51 //有序向量
     52 void LowDuplicate() // 有序向量的唯一化   低效版  O(n^2)
     53 {
     54     int i = 0;
     55     while (i<Size)
     56     {
     57         (Vector[i] == Vector[i + 1]) ? DeleteOne(i+1) : i++;
     58     }
     59 }
     60 
     61 int HighDuplicate()   //有序向量的唯一化  高效版  O(n)
     62 {
     63     /*int i = 0;
     64     int j = 1;
     65     while (i<Size)
     66     {
     67         if (Vector[i] == Vector[j])
     68             j++;
     69         Delete(i + 1, j + 1);
     70         i = j+1;
     71     }*/ //错误写法 利用delete(lo,hi)并不能达到高效率 
     72     //直接从后面截取
     73     int i = 0;
     74     int j = 0;
     75     while (j < Size)
     76     {
     77         if (Vector[i] != Vector[j])
     78             Vector[++i] = Vector[j];
     79         else
     80             j++;
     81     }
     82     //int size = ++i; shrink();   //直接删除掉尾部的多余元素
     83     return j - i;// 返回删除元素总数
     84     /*上面这个可写成
     85     int i=0,j=0;
     86     while(++j<size)
     87     {
     88         if(Vector[i]!=Vector[j])
     89             Vector[++i]=Vector[j];
     90     }
     91     */
     92 }
     93 
     94 //二分查找     O(LogN)   //减而治之
     95 //下面三个版本A
     96 /*int BinarySearch(int Element, int lo, int hi) //二分查找1  对特殊情况未做处理    //左右转向代价不平衡
     97 {
     98     while (lo<=hi)
     99     {
    100         int i = (lo + hi) / 2;
    101         if (Element < Vector[i])
    102             hi = i-1;
    103         else if(Element>Vector[i])
    104             lo = i+1;
    105         else
    106             return i;
    107     }
    108     return -1;
    109 }*/
    110 /*int BinarySearch(int Element, int lo, int hi)     //二分查找2  对特殊情况处理不够好
    111 {
    112     if (lo >= hi)
    113         return hi;
    114     int i = (lo + hi) / 2;
    115     if (Element < Vector[i])
    116         return BinarySearch(Element, lo, i-1);
    117     else if (Element > Vector[i])
    118         return BinarySearch(Element, i+1, hi);
    119     else
    120         return i;
    121 }*/
    122 /*int BinarySearch(int Element, int lo, int hi)  //二分查找3 邓公实现方式 我未完善
    123 {
    124     
    125     while (lo<hi)
    126     {
    127         int i = (lo + hi) >> 1;     // 位运算比乘除法快
    128         if (Element < Vector[i])
    129             hi = i;
    130         else if (Vector[i] < Element)
    131             lo = i + 1;
    132         else
    133             return i;
    134     }
    135     return -1; 
    136 }*/            //上面三个思路都是一样的 选取中间为切分点(轴点)
    137 
    138 /*int BinarySearch(int Element, int lo, int hi)    //版本B 二分查找改进版 将判断从三个改为两个 牺牲刚好命中节点的情况 来换取左右每次转向的代价平衡
    139 {                                                //相较于上面的版本 这种算法在最好(坏)的情况下更坏(好)
    140     /*while (1<hi-lo)                            //各种情况下的SL(search length?)更加接近 整体性能趋于稳定
    141     {
    142         int i = (lo + hi) / 2;
    143         if (Element < Vector[i])
    144             hi = i;
    145         else
    146             lo = i;
    147     }
    148     if (Element == Vector[lo])
    149         return lo;
    150     else
    151         return -1;*/
    152     //上面这个可写成
    153     /*while(1 < hi - lo)
    154     {
    155         int i = (lo + hi)>>1;
    156         (Element < Vector[i]) ? hi = i : lo = i;
    157     }
    158     return (Element == Vector[lo]) ? lo :-1;
    159 }*/
    160 
    161 int BinarySearch(int Element, int lo, int hi)      //版本C 满足了找到不大于元素Element的最大秩
    162 {
    163     while (lo<hi)
    164     {
    165         int i = (lo + hi) / 2;
    166         (Element < Vector[i]) ? hi = i : lo = i + 1;     //对于小于所有数组内值 的元素 i会变为0
    167                                                         //对于大于所有数组内值  的元素 i会变为Size
    168                                                         //对于大于某一部分数组内值 的元素 i最终会变为 该数组元素下标加一
    169     }
    170     return --lo;          
    171 }
    172 
    173 //Fibonacci查找算法    //使向左的操作变多 向右的操作变少   O(logN)
    174 //Fibonacci 查找的算法的 ASL(average searth length  平均查找长度) (在常数意义上)优于二分查找
    175 void Fibonacci(int* F,int size) 
    176 {
    177     F[0] = F[1] = 1;
    178     for (int i = 2; i < size; i++)
    179             F[i] = F[i - 1] + F[i - 2];
    180 }    
    181 /*int FibonacciSearch(int Element,int lo,int hi) //这个做法补全了元素 是得任意的数组都可以满足Fibonacc查找的条件
    182 {
    183     int fib[Size];
    184     Fibonacci(fib, Size);
    185     int k = 0;
    186     while (hi > fib[k]-1)               //找到以个Fibonacc的元素使其减一后大于等于元素总数
    187         k++;
    188     for (int i = hi; hi < fib[k] - 1; i++)     //补全数组 使数组依旧有序
    189         Vector[i] = Vector[hi - 1];
    190     while (lo<hi)
    191     {
    192         int i = (lo + fib[k - 1] - 1);              //选取的位置
    193         if (Element < Vector[i])
    194         {
    195             hi = i;
    196             k -= 1;                         //在左侧的话减一
    197         }
    198         else if (Vector[i] < Element)
    199         {
    200             lo = i + 1;
    201             k -= 2;                            //在右侧的话减二
    202         }
    203         else
    204             return i;
    205     }
    206     return -1;
    207 }*/
    208 int FibonacciSearch(int Element, int lo, int hi)   //这个更加容易理解 利用切分点对有序向量进行划分
    209 {                                                    //利用Fibonacc数列分割 使得每次向左操作数多一点  因为向左只需要比较一次
    210     int fib[Size];
    211     Fibonacci(fib, Size);
    212     int k = 19;
    213     while (lo<hi)
    214     {
    215         while (hi - lo < fib[k])      //找到一个Fibonacc数列某个元素使其 尽可能刚好小于 数组元素总数  
    216                 k--;                //这就是不断找到可以用来分割 数组的 Fibonacc数列的元素
    217         int i = lo + fib[k] - 1;
    218         if (Element < Vector[i])
    219             hi = i;
    220         else if (Vector[i] < Element)
    221             lo = i + 1;
    222         else
    223             return i;
    224     }
    225     return -1;
    226 
    227 }
    228 
    229 //插值查找      //假设已知有序向量中各元素随机分布的规律    O(loglogN)  小写的o
    230 
    231 //比如均匀且独立的分布   当然这是最为简单的一种情况
    232 //这时候 数组中的元素按线性趋势增长
    233 //平均情况:每经过一次比较 n缩至根号n
    234 int InterpolationSearch(int Element,int lo,int size)     
    235 {
    236     int hi = size - 1;                       //与二分查找 Fibonacc查找不同的是  插值查找的左边界被包含在内
    237     while (lo<hi)                            //因为计算是需要用秩访问最后一个元素
    238     {
    239         int i = lo + (hi - lo) * (Element - Vector[lo]) / (Vector[hi] - Vector[lo]);    //线性趋势增长的规律
    240         //(Element < Vector[i]) ? hi = i : lo = i + 1;
    241         if (i > size - 1)
    242             return size - 1;
    243         if (Element < Vector[i])
    244             hi = i;
    245         else if (Element > Vector[i])
    246             lo = i + 1;
    247         else
    248             return i;
    249     }
    250     return --lo;
    251 }
    252 // 插值查找对于处理较大数据时具有的优势更大
    253 //因此应该先用插值查找将范围缩小的一定范围 再进行二分查找
    254 int main()
    255 {
    256     /*for (int i = 0; i < Size; i++)
    257     {
    258         printf("%d ", Vector[i]);
    259     }
    260     printf("
    ");
    261     int Element=0;
    262     while(scanf("%d", &Element))
    263         printf("%d
    ",BinarySearch(Element, 0, Size));  //二分查找*/
    264     /*for (int i = 0; i < 7; i++)
    265     {
    266         printf("%d ", Vector[i]);
    267     }
    268     int Element = 0;
    269     printf("
    ");
    270     while (scanf("%d", &Element))
    271         printf("%d
    ", FibonacciSearch(Element, 0, 7));   //Fibonacc查找  */
    272     for (int i = 0; i < Size; i++)
    273         {
    274             printf("%d ", Vector[i]);
    275         }
    276         printf("
    ");
    277         int Element=0;
    278         while(scanf("%d", &Element))
    279             printf("%d
    ",InterpolationSearch(Element, 0, Size));  //插值查找
    280 }
    View Code

    以前写代码时写注释写的少   。。导致现在注释写的很难看。。。。

     

     

  • 相关阅读:
    MySQL与Redis结合方案
    Linux系统如何监控服务器硬件、操作系统、应用服务和业务
    【MySQL】MySQL复制之防崩溃从节点
    Linux系统vim编辑器换行至文件的行首及行尾操作
    Xtrabackup远程备份
    innodb_force_recovery参数分析
    Oracle异构平台迁移利器之XTTS(使用rman方式)
    ES6基础语法
    读郭老师推荐书籍--《原则》
    PhpStorm 的基本应用
  • 原文地址:https://www.cnblogs.com/57one/p/11402573.html
Copyright © 2020-2023  润新知