数据结构复习,从头看了《数据结构与算法分析(c 描述)》这本书,并自己动手实现书中的大部分例子与习题代码。
1. 选择问题
通过 选择问题 ( selection problem ) 解释了不同算法在较大输入情况下的运行性能与在适量输入情况下的运行性能具有同等重要性。
问题: 从 N 个数中确定其中第 k 个最小者。
算法1: 任意排序算法(冒泡排序)以递增顺序将数组排序,返回位置 k 上的元素。
算法2:将前 k 个元素读入数组并排序,将剩下的元素再逐个读入,与数组中第 k 个元素比较,若比之小则忽略,否则将其放到数组中正确位置。
算法3 :快速排序算法变形。选取枢纽元,像快排算法一样对剩下数组划分成两个子集S1, S2,若 k <= |S1|,对 S1 做递归; 若 k = |S1|,直接返回; 否则对 S2 做递归。
下面代码实现 算法1 与 算法3,附带测试程序:
#include <stdio.h>
#include <stdlib.h>
void swap(int *a, int *b) {
int temp;
temp = *b;
*b = *a;
*a = temp;
}
void bubbleSort(int *array, int size) {
int temp;
for (int i = size - 1; i > 0; i--)
for (int j = 0; j < i; j++) {
if (array[j] > array[j + 1]) {
swap(&array[j], &array[j + 1];
}
}
for (int i = 0; i < size; i++)
printf("num %d: %d\n", i, array[i]);
}
int median3(int *array, int left, int right) {
int median = (left + right)/2;
if (array[left] > array[median])
swap(&array[left], &array[median]);
if (array[left] > array[right])
swap(&array[left], &array[right]);
if (array[median] > array[right])
swap(&array[median], &array[right]);
swap(&array[median], &array[right - 1]);
return array[right - 1];
}
void quickSelect(int *array, int left, int right, int k) {
int pivot;
pivot = median3(array, left, right);
int i = left, j = right - 1;
for ( ; ; ) {
while(array[++i] < pivot);
while(array[--j] > pivot);
if ( i < j )
swap(&array[i], &array[j]);
else
break;
}
swap(&array[i], &pivot);
if ( k <= i )
quickSelect(array, left, i - 1, k);
else if (k > i + 1)
quickSelect(array, i + 1, right, k);
}
int main() {
int array[20];
for (int i = 0; i < 20; i++) {
array[i] = (double)rand()/RAND_MAX * 100 ;
printf("num %d: %d\n", i, array[i]);
}
/*bubbleSort(array, 20);*/
quickSelect(array, 0, 19, 10);
printf("k-th big num is :%d\n", array[9]);
}
2. 递归简论
在编写递归程序的时候,关键要牢记递归的四条基本法则:
- 基准情形
- 不断推进
- 设计法则。假设所有的递归调用都能运行
- 合成效益