排序
插入排序
//插入排序
直接插入排序
#define maxsize 1024 //文件最大长度
typedef int keytype; //设key值为整型
typedef struct //记录类型
{
keytype key; //记录关键字
... //记录其他域
}Retype;
typedef struct //文件或表的类型
{
Retype R[maxsize+1]; //文件存储空间
int len; //当前记录数
}sqfile;
void Insort(sqfile F) //对顺序文件F直接插入排序的算法
{
int i, j;
for(i = 2; i <= F; i++) //插入n-1个记录
{
F.R[0] = F.R[i]; //待插入记录先存于监视哨
j = i - 1;
while(F.R[0].key < F.R[j].key) //key比较
{
F.R[j + 1] = F.R[j]; //记录顺序后移
j--;
}
F.R[j+1] = F.R[j]; //原R[i]插入j+1位置
}
}
折半插入排序
void Binsort(sqfile F) //对文件F进行折半查找的算法
{
int i, j, low, high, mid;
for(i = 2; i <= F; i++) //插入n-1个记录
{
F.R[0] = F.R[i]; //带插入记录存入监视哨
low = 1; high = i-1;
while(low <= high) //查找R[i]的位置
{
mid = (low + high) / 2;
if(F.R[0].key >= F.R[mid].key)
low = mid + 1; //调整下界
else
high = mid - 1; //调整上界
}
for(j = i - 1; j >= low; j--)
F.R[j+1] = F.R[j]; //记录顺移
F.R[low] = F.R[0]; //原R[i]插入low位置
}
}
链表插入排序
typedef struct node //存放记录的节点
{
keytype ley; //记录关键字
... //记录其他域
struct node *next; //链指针
}Lnode, *linklist;
void Linsertsort(linklist L) //链表插入排序算法
{
linklist p, q, r, u;
p = L->next; //p为描述节点指针
L->next = NULL: //置字表为空
while(p) //若待排序节点存在
{
r = L; q = L->next; //r为q的前驱指针
while(q&&p->key <= p->key) //找p节点的位置
{r = q; q = q->next;}
u = p->next;
p->next = q; //p节点为q节点的前驱插入
r->next = p;
p = u;
}
}
Shell排序
void Shellsort(sqfile F) //对顺序文件F按Shell方法排序的算法
{
int i, j, d;
d = F.len / 2; //第一次增量
while(d >= 1)
{
for(i = d+1; i <= F.len; i++) //本趟的希尔排序
{
F.R[0] = F.R[i];
j = i - d;
while((j > 0) && (F.R[0].key < F.R[j].key))
{
F.R[j+d] = F.R[j]; //记录移动
j = j - d;
}
F.R[j+d] = F.R[0];
}
d = d / 2; //形成新的增量
}
}
冒泡排序
//冒泡排序
void Bubsort(sqfile F) //对顺序文件气泡排序的算法
{
int i, flag; //flag为记录交换次数的标记
Retype temp;
for(j = F.len; i >= 2; i--) //最多n-1趟排序
{
flag = 0;
for(j = 1; j <= i-1; j++) //一趟气泡排序
if(F.R[j].key > F.R[j+1].key) //两辆比较
{
temp = F.R[j]; //R[j] <=> R[j+1]
F.R[j] = F.R[j+1];
F.R[j+1] = temp;
flag = 1;
}
if(flag == 0) break; //无记录交换时排序完毕
}
}
快速排序
//快速排序
typedef struct //栈元素类型
{
int low, high; //存放末排子表的上下界
}stacktype;
int qkpass(sqfile F, in low, int high)
//对文件F中当前子表(R[low]...R[high])一趟快速排序的算法
{
int i = low, j = high;
keytype x = F.R[low].key; //存入基准key
F.R[0] = F.R[low]; //存入基准记录
while(i < j)
{
while(i < j && x <= F.R[j].key) y--; //逆序比较
if(i < j) F.R[i] = F.R[j]; //比x小的key左移
while(i < j && x >= F.R[i].key) i++; //正序比较
if(i < j) F.R[j] = F.R[i]; //比x大的key右移
}
F.R[i] = F.R[0]; //基准记录存入第i位置
return (i); //返回基准位置
}
void qksort(sqfile F) //对文件F快速排序的算法(非递归)
{
int i, low, high;
stacktype u; //栈元素
Clearstack(S); //置栈空
u.low = 1; u.high = F.len;
Push(S, u);
while(!Emptystack(S))
{
u = Pop(S); //退栈
low = u.low; high = u.high; //取当前表的上下界
while(low < high)
{
i = qkpass(F, low, high); //对当前子表的一趟快排
if(i + 1 , high)
{
u.low = i + 1; u.high = high; //i位置的右部上下界进栈
Push(S, u);
}
}
high = i - 1; //排当前位置的左部
}
}
选择排序
//选择排序
void Slectsort(sqfile F)
{
int i, j, k;
Retype temp;
for(i = 1; i < F.len; i++) //选择n-1趟
{
j = i; //j为本趟选择的最小key记录的序号
for(k = i + 1; k < F.len; k++) //本趟选择
if(F.R[k].key < F.R[j].key) j = k;
if(i != j)
{
temp = F.R[i];
F.R[i] = F.R[j];
F.R[j] = temp;
}
}
}
堆排序
//堆排序
筛选算法描述
void ADjust(sqfile F, int s, int n) //将(F.R[s]...F.R[n])调整成大根堆的算法
{
Retype temp;
int j;
temp = F.R[s]; //暂存F.R[s]
j = 2*s; //令j为s节点的左子序号
while(j <= n)
{
if(j < n && F.R[j+1].key > F.R[j].key) j++; //令j为s的左右孩子key的最大者编号
if(F.R[j].key > temp.key)
{
F.R[s] = F.R[j]; //R[j] => R[s]
s = j; j = 2 * s; //置新的调整点
}
else break; //调整完毕,退出循环
}
F.R[s] = temp; //最初的根回归
}
void Heapsort(sqfile F) //对顺序文件F的堆排序算法
{
int i;
Retype temp;
for(i ;= F.len / 2; i >= 1; i--)
{
Adjust(F, i, F.len) //调整(R[i]...R[n])为堆
}
for(i = F.len; i >= 2; i--) //选择n-1次
{
temp = F.R[1]; //根与当前最后一个节点互换
F.R[1] = F.R[i];
F.R[i] = temp;
Adjust(F, 1, i-1); //互换后再建堆
}
}
归并排序
//归并排序
void Tmerge(sqfile F, sqfile F1, int s, int m, int t) //相邻两个子文件的归并算法
{
int i, j, k, r;
i = s, j = m + 1; //扫描指针初值
k = s; //k为目标文件的记录指针
while((i < m) && (j <= t))
if(F.R[i].key <= F.R[j].key)
{
F1.R[k] = F.R[i]; //R[i]送目标文件
i++; k++;
}
else
{
i = j; r = t;
}
if(i <= m) r = m;
else
{
i = j; //置剩余部分的起始序号
r = t;
}
while(i <= r)
{
F>R[k] = F.R[i]; //复制子文件的剩余部分
i++; k++;
}
}
编程实现 O(n) 时间复杂度内找到一组数据的第 K 大元素
查找
实现一个有序数组的二分查找算法
实现模糊二分查找算法(比如大于等于给定值的第一个元素)
//二分查找
int Binsearch(sqlist r, keytype k)
{
int low, high, mid;
low = 1; high = r.len;
while(low <= high)
{
mid = (low + high) / 2;
if(k == r.data[mid].key) return(mid);
if(k < r.data[mid].key) high = mid - 1;
else low = mid + 1;
}
return(0);
}