第一章:二分查找
1.2 二分查找
p7
#include<iostream>
using namespace std;
int main()
{
int arr[5] = { 1,2,3,4,5 };
int item = 2;
int count = 0; //记录查找了几次
int arrayLen = sizeof(arr) / sizeof(arr[0]);
//cout << sizeof(arr) << " " << sizeof(arr[0]) << endl; // 20 4
//cout << arrayLen << endl; // 5
int low = 0; //元素下标,第零个位置,第1个元素
int high = arrayLen - 1; //第 4个位置,第五个元素
int result = -1; //没找到返回 -1
while (low <= high)
{
int mid = (low + high) / 2;
count++;
if (item == arr[mid])
{
cout <<"找到了,下标为 "<< mid << ", 值为 "<< arr[mid]<< endl; //输出结果
cout << "共查找了 " << count << " 次" << endl;
return 0;
}
else if (item < arr[mid])
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
cout << result << endl; //没有找到,返回-1
system("pause");
return 0;
}
p8
练习1.1 :log128 = 7步
练习1.2:log256 = 8步
1.3 大O表示法
p13
1.3:可以根据字母姓氏进行二分查找,O(log n)
1.4:O(n)
1.5:O(n)
1.6:O(n)
第二章:选择排序
p22
2.1:链表
2.2:经常要执行插入操作——服务员添加点菜单,而链表的插入速度很快;而且不需要执行查找和随机访问操作(这是数组擅长的),因为厨师总是从队列中取出第一个点菜单。综上所述,使用链表合适。
2.3:有序数组
2.4:数组的插入速度很慢。另外如果要使用二分查找算法来查找用户名,数组必须是有序的,因此每次插入用户名后,都必须对数组进行排序
2.5:查找时,其速度比数组慢,但比链表快;而在插入时,其速度比数组快,但与链表相当。因此,除了查找速度比数组慢,其他方面并不比链表慢。
2.3 选择排序
p28
将数组元素按从小到大顺序排列
#include <iostream>
using namespace std;
int main()
{
int arr[10] = { 1,4,5,8,9,6,2,3,7,10 };
int length = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length; j++)
{
if (arr[i] > arr[j])
{
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
for (int i = 0; i < length; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
第三章:递归
p36
递归调用栈
#include <iostream>
using namespace std;
int func(int n)
{
if (n == 1)
return 1;
else
return n * func(n-1);
}
int main()
{
int x;
cin >> x;
cout << func(x) << endl;
system("pause");
return 0;
}
p40
3.2:栈将不断地扩大。因为每个程序可使用的调用栈空间有限,程序用完这些空间后,将因栈的溢出而终止。
第四章:快速排序
p47 练习
#include <iostream>
using namespace std;
//递归求和
int sum(int arr[],int len)
{
//法1:
if (len == 0)
return 0;
else
return arr[len-1] + sum(arr,len-1);
法2:
//return len == 0 ? 0 : arr[len - 1] + sum(arr, len - 1);
}
//递归求元素个数
int count(int* arr,int len)
{
if (len == 0)
return 0;
else
return 1 + count(arr, len - 1);
}
//递归求最大值
int max(int* arr, int len)
{
if (len == 1) // 基线条件
return arr[0];
int temp = max(arr+1, len - 1); // 指针 +1 表示从下一个元素开始
if (arr[0] > temp)
return arr[0];
else
return temp;
}
//非递归求最大值
//int max1(int* arr, int len)
//{
// int max = arr[0];//假设第一个元素为最大值
// for (int i = 0; i < len; i++)
// {
// if (max < arr[i])
// max = arr[i];
// }
// return max;
//
//}
int main()
{
int arr[] = {1,2,3,4,1,1};
int len = sizeof(arr) / sizeof(arr[0]);
cout << sum(arr, len) << endl;
cout << max(arr, len) << endl;
cout << count(arr, len) << endl;
system("pause");
return 0;
}
二分查找基线条件:
- 数组只包含一个元素。如果如果要查找的值与这个元素相同,就找到了;否则说明不在数组中。
二分查找递归条件:
- 把数组分成两半,将其中一半丢弃,并对另一半执行二分查找。
p52:快速排序
#include <iostream>
using namespace std;
//找出基准元的下标,并且完成元素的分块
// 小的放左边,大的放右边
//找出基准元的方法很多,取第一个或者最后一个都不是一个好方法
//具体可以自行上网查阅资料
int Sort(int arr[], int left, int right)
{
//取第一个元素为基准元
int pivotValue = arr[left];
//使用双向扫描法完成分块:left从左向右扫描,right从右向左扫描
//基准元的左边都小于他,右边都大于他
//right 扫描完成后,left 扫描,left扫描完成后 right 扫描
//当left==right,说明扫描结束,完成分块
while (left < right)
{
//通过 right 可以把比基准元小的放到左边
while (left < right && arr[right] >= pivotValue)
{
right--;
}
arr[left] = arr[right];
//通过 left 可以把比基准元小的放到左边
while (left < right && arr[left] <= pivotValue)
{
left++;
}
arr[right] = arr[left];
}
arr[left] = pivotValue; //数组分成了两部分,比 pivotValue 小的在左边,大的在右边
return left;
}
void quickSort(int arr[], int left, int right)
{
if (left < right)
{
//分块后基准元的下标
int pivot = Sort(arr, left, right);
//对分块后的部分进行排序
quickSort(arr, left, pivot - 1);//递归: 对 0--6 (左边)位置的元素进行排序
quickSort(arr, pivot + 1, right); // 递归 :对 8--9 (右边)位置的元素进行排序
}
}
int main()
{
int arr[10] = { 8,4,5,1,9,6,2,3,7,10 };
int length = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, length - 1);
for (int i = 0; i < length; i++)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
p56
4.5:O(n)
4.6:O(n)
4.7:O(1)
4.8:O(n^2)