数据结构总复习+错题+一些不清楚的点。
大复习模式,开启!!
不急不躁,复习就要复习透彻!
(慕课错题如果有错误,那就是我搜出来的不对,毕竟测试答了之后也不给答案啊😢
欢迎在评论区里踢我捉错误🐱
持续更新ing
文章目录
第八章+第一章,排序+时间复杂度
慕课错题:
-
设有5000个待排序的记录关键字,如果需要用最快的方法选出其中最小的10个记录关键字,则用下列( 堆排序 )方法可以达到此目的
只有堆排序每次最快选出来一个最小的一个,其他都不可以一趟出一个最小,只有堆排序是一次又一次的最小。
堆排序,快速排序,希尔排序,归并排序适合处理数据量大的序列。
-
在对n个元素进行快速排序的过程中,最坏情况下需要进行( n-1)趟
也就是每一次都没有任何元素动,n-1次定下了n-1个元素的位置,最后一个就不用动了。
-
在数据结构中,从逻辑上可以把数据结构分成(线性结构和非线性结构)
-
算法评价标准包括正确性、可读性、健壮性和(高效性)
-
计算机算法指的是解决问题的有限运算序列,(有穷性、确定性、可行性)等五个特性。
插入排序
主函数和打印函数:
void print(int* sortArr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", sortArr[i]);
}
}
int main()
{
int i, j,len;
int sortArr[] = { 151,130,92,461,42,77,183,130,20,523,7 };
len = sizeof(sortArr) / sizeof(sortArr[0]);
//Insert_direct(sortArr,len);
//Bin_sort(sortArr, len);
//Shell_sort(sortArr, len);
}
排序1:直接插入排序(每次都是一点点点的比较)
- 时间复杂度O(n^2)
void Insert_direct(int* sortArr,int len)//直接插入排序,升序排列的。
{
int i, j;
int temp;
void print(int* sortArr, int len);
for (i = 1; i < len; i++)
{
j = i - 1;
temp = sortArr[i];
while (j >= 0 && temp < sortArr[j])
{
sortArr[j + 1] = sortArr[j];
j--;//往后挪,每次j+1的地方就是需要填的位置(也就是未减前,已经被保存的j的位置)
}
if (j + 1 != i)//若等于,刚好不用动。
{
sortArr[j + 1] = temp;
}
//printf("%d:", i);
//print(sortArr, len);
//printf("\n");
}
}
排序2:二分插入排序
- 时间复杂度(O(n^2))
void Bin_sort(int* sortArr, int len)
{
int i, j, high, mid, low,temp;
for (i = 1; i < len; i++)
{
temp = sortArr[i];
low = 0;
high = i-1;//i是要插的,只要二分查找前面的就行。
while (low <= high)//必须要有等号
{
mid = (low + high) / 2;
if (sortArr[i] < sortArr[mid]) high = mid - 1;//并且如果是小于的话,要插入位置是low,这二者除了对于二分之外,还对最后结果也是恰当的。
else low = mid + 1;//如果大于,就是low+1的位置。
}//最终low的位置是需要插入的位置
if (low != i)
{
for (j = i - 1; j >=low; j--)//挪位置,注意,把low的位置挪出来就行
{
sortArr[j + 1] = sortArr[j];
}
sortArr[low] = temp;
}
//printf("%d:", i);
//print(sortArr, len);
//printf("\n");
}
}
碎碎念:看着挺简单的东西,不看书自己敲一遍,中间还真的会出现不少错误,呜呜呜,我个菜鸡🐔
排序3:shell排序(希尔排序)
-
时间复杂度:O(n^1.3)
本质上是按照增量分组后,分别进行直接插入排序。
算法是从增量的开始,与前方比较(也就是每一组的第二个和第一个比,然后第三个往前比)
不过是不是按照每个组的顺序来的,是第一组的第二个、第二组的第二个。。。。
例题见8-1.
(为什么不发出来呢?手写到本上了,字丑拒绝😆)
void Shell_sort(int* sortArr, int len)
{
int d = len / 2;//增量
int i, j,temp;
for (; d > 0; d /= 2)
{
for (i = d; i < len; i++)//一趟排序
{
temp = sortArr[i];
j = i - d;//同组内j是i前面的数
while (j >= 0 && temp < sortArr[j])
{
sortArr[j + d] = sortArr[j];
j -= d;
}
if(j+d!=i)sortArr[j + d] = temp;//注意位置。别出了这个循环
}
//print(sortArr, len);
//printf("\n");
}
}
📓:插入算法中的直接插入排序算法和二分插入排序算法都默认将第一个数加入到初始序列中了。
选择排序
排序1:直接选择排序
- 时间复杂度O(n^2)
本质就是对于每一个位置,都从它以及它之后的序列中找最小,然后单独交换这两个,避免了不断的移动数组,但是本身需要移动很多次。
- 算法很简单,就不写了。
考试老师说只考前三个算法,所以就懒得写了
排序2:堆排序
- 时间复杂度O(nlog2n)
小根堆排出降序(由大到小),大根堆排出升序
交换后的元素不再参与堆的调整,交换到只剩一个元素后完成.
- 算法分为调整部分和排序部分,调整是从最后一个非叶子结点,逐步往前进行调整,采用循环的方式,若上层发生变化,也会对下层产生影响,进而继续调整下层,直到结点大于size.
- 排序是交换第一个和最后一个数,直至只剩第一个数.每交换一次,就让size-1,并且只针对交换的头节点进行调整部分的调整(会层层往下进行的).
交换排序
排序1:冒泡排序
- 时间复杂度(O(n^2))
最基本的最简单的全对比都会,不赘述了
主要是可以定义一个交换标志,如果未发生交换,终止进程(排好了)
冒上去的泡就不用再比较了
排序2:快速排序
- 时间复杂度O(nlog2n)
定枢轴,左右摇摆着交换🐕
算法采用递归的形式,将每一趟进行了递归.
枢轴一般是定义为左侧的第一个
难点:
- 注意设置退出标志:即i<j不成立了,也就是i=j了,指向一趟的终止了.
- 总循环的结束标志也是i=j;
- 递归的时候重新设置左右两边区间的左右.
:快速排序
- 时间复杂度O(nlog2n)
定枢轴,左右摇摆着交换🐕
算法采用递归的形式,将每一趟进行了递归.
枢轴一般是定义为左侧的第一个
难点:
- 注意设置退出标志:即i<j不成立了,也就是i=j了,指向一趟的终止了.
- 总循环的结束标志也是i=j;
- 递归的时候重新设置左右两边区间的左右.