数据结构学习第八天

18:35:51 2019-08-23

学习

无序向量的操作 以及  有序向量 二分查找  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 int main()
229 {
230     for (int i = 0; i < Size; i++)
231     {
232         printf("%d ", Vector[i]);
233     }
234     printf("\n");
235     int Element=0;
236     while(scanf("%d", &Element))
237         printf("%d\n",BinarySearch(Element, 0, Size));  //二分查找
238     /*for (int i = 0; i < 7; i++)
239     {
240         printf("%d ", Vector[i]);
241     }
242     int Element = 0;
243     printf("\n");
244     while (scanf("%d", &Element))
245         printf("%d\n", FibonacciSearch(Element, 0, 7));   //Fibonacc查找  */
246 }

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

原文地址:https://www.cnblogs.com/57one/p/11402573.html

时间: 2024-07-30 17:07:27

数据结构学习第八天的相关文章

小猪的数据结构学习笔记(四)

小猪的数据结构学习笔记(四) 线性表之静态链表 --转载请注明出处:coder-pig 本章引言: 在二,三中中我们分别学习了顺序表中的线性表与单链表,线性表有点类似于 我们前面所学的数组,而单链表使用的最多的是指针,这里问个简单的问题, 如果是在以前没有指针的话,前辈先人们怎么实现单链表呢?大家思考下! 没有指针,那么用什么来代替呢?前辈先人们非常机智,想出了使用下标+游标的方式 来实现单链表的效果!也就是今天要讲的--静态链表! 当然你也可以直接跳过本章,因为有了单链表就没有必要用静态链表了

小猪的数据结构学习笔记(二)

小猪的数据结构学习笔记(二) 线性表中的顺序表 本节引言: 在上个章节中,我们对数据结构与算法的相关概念进行了了解,知道数据结构的 逻辑结构与物理结构的区别,算法的特性以及设计要求;还学了如何去衡量一个算法 的好坏,以及时间复杂度的计算!在本节中我们将接触第一个数据结构--线性表; 而线性表有两种表现形式,分别是顺序表和链表;学好这一章很重要,是学习后面的基石; 这一节我们会重点学习下顺序表,在这里给大家一个忠告,学编程切忌眼高手低,看懂不代表自己 写得出来,给出的实现代码,自己要理解思路,自己

数据结构学习日记2:实现一个简单的线性表功能(链式存储方式)

数据结构学习日记,此次是用链表来实现一个线性表的功能 // ListTable1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using namespace std; #define ERROR 0; #define OK 1; typedef int Status; typedef int ElemType; //声明一个节点 typedef struct Node { ElemType d

数据结构学习之二叉排序树

介绍:二叉排序树是以一定的规则排列树中元素,因而可以进行快速的排序和查询的树状数据结构,一般规则是:对于树中任意一个节点,左孩子严格小于根,根严格小于右孩子,有点像大根堆.(只是大根堆中左右孩子关系并不确定,且和根的关系是统一的,而且有上浮和下沉操作使得大根堆总是一棵完全二叉树,其不断弹出堆顶形成有序列的过程叫做堆排序.虽然二叉排序树中也有旋转操作使得树尽量平衡,但是由于数值大小分明的左右孩子,在进行平衡操作时远不如大根堆方便快捷.)对于一棵已经构造完成的排序二叉树,它的中序遍历序列即为升序排列

文章分享:简单数据结构学习:单向链表

文章分享:简单数据结构学习:单向链表:https://www.textarea.com/aprikyb/jiandan-shujujiegou-xuexi-danxiang-lianbiao-252/

数据结构学习系列之线性表(三)

前言数据结构学习,发现坚持下来比较难,本次学习与上次学习间隔了几个月,不管怎样还是要强迫自己坚持下来. 静态链表 用数组模拟链式结构的线性表,对于没有指针的编程语言,只能使用这种方式来模拟.这是大师们想出来的实现方法,体会大师们的编程思路,站在大师们的肩膀上解决一个又一个的难题.每个节点包含一个游标(数组数字索引),用于指向下个节点,所以静态链表也称为游标链表.规定数组第一个元素为备用链表(未被使用的数组游标,静态链表初始化时,会生成备用链表)的头节点,数组最后一个元素为链表的头节点.当需要插入

九、Android学习第八天——广播机制与WIFI网络操作(转)

(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 九.Android学习第八天——广播机制与WIFI网络操作 今天熟悉了Android中的广播机制与WIFI网络的一些基本操作,总结如下: Android的广播机制 我们知道广播机制中,发送方不会关心接收方时候接收到数据或者如何去处理数据. 这里总结下Android中BroadcastReceiver的注册方法: (一)在应用程序中进行注册 (二)在Manifest.xml

小猪的数据结构学习笔记(五)

小猪的数据结构学习笔记(五) 线性表之--循环链表                           --转载请注明出处:coder-pig 循环链表知识点归纳: 相关代码实现: ①判断是否为空表: ②单循环链表的存储结构 其实和单链表的结构是一样的! /*定义循环链表的存储结构*/ typedef struct Cir_List { int data; struct Cir_List *next; }Lnode; ③初始化循环单链表 代码如下: //1.循环链表的初始化 //表示一个元素,如

数据结构学习笔记之栈

栈(stack)  是限定仅在表尾进行插入或删除操作的线性表.因此,对栈来说,表尾端有其特殊含义,称为栈项(top),相应地,表头端称为栈底(bottom).不含元素的空表称为空栈. 栈有两种存储表示方法:顺序栈和链栈.顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置.通常的习惯做法是以top=0表示空栈,鉴于C语言中数组的下标约定从0开始,则当以C作描述语言时,如此设定会带来很大不便:另一方面,由于栈在使用过程