C各种排序

 

各种查找与排序算法


1. 顺序查找的算法
int Search_Seq ( SSTable ST, KeyType key ) {
// 在有序表 ST 中顺序查找其关键字等于 key 的数据元素。
// 如果找到,则函数值为该元素在表中的位置,否则为 0。
ST.elem[0].key = key; //“哨兵”
for ( i = ST.length; ! ( ST.elem.key = key ); --i ); // 从后往前找
return i; // 找不到时,i 为 0
} // Search_Seq
 
2. 折半查找的算法
int Search_Seq ( SSTable ST, KeyType key ) {
// 在有序表 ST 中折半查找其关键字等于 key 的数据元素。
// 如果找到,则函数值为该元素在表中的位置,否则为 0。
low = 1; high = ST.length; // 置区间初值
while ( low <= high ) {
mid = ( low + high ) / 2;
if ( key = ST.elem[mid].key ) return mid; // 找到待查记录
else if ( key < ST.elem[mid].key )
high = mid – 1; // 继续在前半区间进行查找
else low = mid + 1; // 继续在后半区间进行查找
} // while 结束
return 0; // 有序表中不存在待查记录
} //Search_Bin
 

3. 二叉排序树的动态查找算法
Status SearchBST ( BiTree T, KeyType key, BiTree f, BiTree &p ) {
// 在根指针 T 所指二叉排序树中递归地查找某关键字等于 key 的数据元素,
// 若查找成功,则指针 p 指向该数据元素结点,并返回 TRUE;
// 否则指针 p 指向查找路径上访问的最后一个结点并返回 FALSE;
// 指针 f 指向 T 的双亲,其初始调用值为 NULL。
if ( ! T ) { p = f; return FALSE; } // 查找不成功
else if ( key = T->data.key ) { // 查找成功
p = T; return TRUE;
} // else if 结束
else if ( key < T->data.key ) // 在左子树中继续查找
SearchBST ( T->lchild, key, T, p );
else SearchBST ( T->rchild, key, T, p ); // 在右子树中继续查找
SearchBST ( T->rchild, key, T, p );
} // SearchBST

 
4. 二叉排序树的插入算法
Status InsertBST ( BiTree &T, TElemType e ) {
// 当二叉排序树 T 中不存在关键字等于 e.key 的数据元素时,
// 插入 e 并返回 TRUE,否则返回 FALSE
if ( ! SearchBST ( T, e, NULL, p ) ) { // 查找不成功
s = ( BiTree ) malloc ( sizeof ( BiTNode ) );
s->data = e; s->lchild = NULL; s->rchild = NULL;
if ( ! p ) T = s; // 被插结点 *s 为新的根结点
else if ( e.key < p->data.key )
p->lchild = s; // 被插结点 *s 为左孩子
else p->rchild = s; // 被插结点 *s 为右孩子
return TURE
} // if 结束
else return FALSE; // 树中已有关键字相同结点不再插入
} // InsertBST

 
5. 二叉排序树的删除算法
Status DeleteBST ( BiTree &T, KeyType key ) {
// 若二叉排序树 T 中存在关键字等于 key 的数据元素时,则删除该数据元素结点
// 并返回 TRUE;否则返回 FALSE
if ( ! T ) return FALSE; // 不存在关键字等于 key 的数据元素
else {
if ( key = T->data.key ) Delete (T); // 找到关键字等于 key 的数据元素
else if ( key < T->data.key ) DeleteBST ( T->lchild, key );
else DeleteBST ( T->rchild, key )
return TRUE;
} // else 结束
} // DeleteBST

Status DeleteBST ( BiTree &p ) {
// 从二叉排序树中删除结点 p,并重接它的左子树或右子树
if ( ! p->rchild ) { // 右子树空,则只需重接它的左子树
q = p; p = p->lchild; free (q);
} // if 结束
else if ( ! p->lchild ) { // 左子树空,则只需重接它的右子树
q = p; p = p->rchild; free (q);
} // else if 结束
else { // 左子树和右子树均不空
q = p; s = p->lchild;
while ( s->rchild ) { // 转左,然后向右到尽头
q = s; s = s->rchild
}
p->data = s->data; // s 指向被删除结点的前驱
if ( q ! = p ) q->rchild = s->lchild; // 重接 q 指针所指的右子树
else q->lchild = s->rchild; // 重接 q 指针所指的左子树
} // else 结束
} // DeleteBST
 
6. 二叉平衡树的旋转算法
(1) 右旋平衡处理。
void R_Rotate ( BSTree &p ) {
// 对以 *p 为根的二叉排序树作右旋处理,处理之后 p 指向新的树根结点,
// 即旋转处理之前的左子树的根结点。
lc = p->lchild; // lc 指向 p 的左子树根结点
p->lchild = lc->rchild; p->bf = 0 // p 左子树指向 lc 右子树,且平衡因子为 0
lc->rchild = p; lc->bf = 0 // lc 右子树指向 p,且平衡因子为 0
p = lc; // p 指向新的根结点,
} // R_Rotate
(2) 左旋平衡处理。
void L_Rotate ( BSTree &p ) {
// 对以 *p 为根的二叉排序树作左旋处理,处理之后 p 指向新的树根结点,
// 即旋转处理之前的右子树的根结点。
rc = p->rchild; // rc 指向 p 的右子树根结点
p->rchild = rc->lchild; p->bf = 0 // p 右子树指向 rc 左子树,且平衡因子为 0
rc->lchild = p; rc->bf = 0 // rc 的左子树指向 p,且平衡因子为 0
p = rc; // p 指向新的根结点,
} // L_Rotate
 
1. 直接插入排序算法
void InsertSort ( SqList &L ) {
// 对顺序表 L 作直接插入排序
for ( i = 2; i <= L,length; ++i )
if ( L.r.key < L.r[i-1].key ) { // 若“<”,则将 L.r 插入有序子表
L.r[0] = L.r; // 复制为哨兵
for ( j = i-1; L.r[0].key < L.r[j].key ); --j )
L.r[j+1] = L.r[j]; // 记录后移
L.r[j+1] = L.r[0]; // 插入到正确位置
} // if 结束
} // InsertSort
 
2. 希尔排序算法
void Shellinsert ( SqList &L, int dk ) {
// 对顺序表 L 作一趟希尔插入排序。此算法和一趟直接插入排序相比,作了以下修改:
// (1) 前后记录为止的增量是 dk,而不是 1;
// (2) r[0] 只是暂存单元,而不是哨兵。当 j <= 0 时,插入位置已经找到。
for ( i = dk+1; i <=L.length; ++i )
if ( L.r.key < L.r[i-dk].key ) { // 需要将 L.r 插入有序增量子表
L.r[0] = L.r; // 暂存在 L.r[0]
for ( j = i-dk; j > 0 && ( L.r[0].key < L.r[j].key ); j -= dk )
L.r[j+dk] = L.r[j]; // 记录后移,查找插入位置
L.r[j+dk] = L.r[0]; // 插入到正确位置
} // if 结束
} // ShellInsert
 
3. 冒泡排序算法
void BubbleSort ( SqList &L ) {
// 对顺序表 L 作冒泡排序。此算法和一趟直接插入排序相比,作了以下修改:
// 前后记录为止的增量是 dk,而不是 1;
// r[0] 只是暂存单元,而不是哨兵。当 j <= 0 时,插入位置已经找到。
for ( i = 0; i <=L.length; ++i )
for ( j = n-2; j > i; --j )
if ( L.r[j+1].key < L.r[j].key ) { // 交换
temp = L.r[j+1];
L.r[j+1] = L.r[j];
L.r[j] = temp;
} // if 结束
} // BubbleSort
 
4. 快速排序算法
int Partition ( SqList &L, int low, int high ) {
// 交换顺序表 L 中子表 r[low . . high] 的记录,“枢轴”记录到位并返回其所在位置
// 此时,在它之前(后)的记录均不大(小)于它。
L.r[0] = L.r[low]; // 用子表第一个记录作“枢轴”记录
pivotkey = L.r[low].key; // pivotkey是“枢轴”记录关键字
while ( low < high ) { // 从表的两端交替地向中间扫描
while ( low < high && L.r[low].key >= pivotkey )
--high;
L.r[low] = L.r[high]; // 比“枢轴”记录小的记录移到低端
while ( low < high && L.r[high].key <= pivotkey )
++low;
L.r[high] = L.r[low]; // 比“枢轴”记录大的记录移到高端
} // while 结束
L.r[low] = L.r[0]; //“枢轴”记录到位
return low; // 返回“枢轴”位置
} // Partition

void Qsort ( SqList &L, int low, int high ) {
// 对顺序表 L 中的子序列 L.r[low . . high] 作快速排序。算法中出现的 pivotloc 是“枢轴”位置。
if ( low < high ) { // 长度大于 1
pivotloc = Partition ( L, low, high ); // 将 L.r[low . . high] 一分为二
Qsort ( L, low, pivotloc -1 ); // 对低子表递归排序
Qsort ( L, pivotloc -1, high ); // 对高子表递归排序
} // if 结束
} // QSort

void QuickSort ( SqList &L ) {
// 对顺序表 L 作快速排序
Qsort ( L, 1, L.length );
} // QuickSort
 
5. 直接选择排序算法
void SelectSort ( SqList &L ) {
// 对顺序表 L 作直接选择排序
for ( i = 1; i < L.length; ++i ) { // 选择第 i 个小的记录,并交换到位
k = i;
for ( j = i+1; j < L.length; ++j ) // 在 L.r[i..length] 中选择 key 最小的记录
if ( L.r[j].key < L.r[k].key ) k = j;
if ( i ! = k ) { // 与第 i 个记录交换
temp = L.r; L.r = L.r[k]; L.r[k] = temp;
} // if 结束
} // for 结束
} // SelectSort
 
6. 堆排序算法
typedef SqList HeapType;
void HeapAdjust ( HeapType &H, int s, int m ) {
// 已知 H.r[s . . m] 中记录的关键字除 H.r[s].key 之外均满足堆的以,
// 此函数调整 H.r[s] 的关键字,使 H.r[s . . m] 成为一个堆。
temp = H.r[s];
for ( j = 2*s; j <=m; j *=2 ) { // 沿着 key 较大的孩子结点向下筛选
if ( j <m && ( H.r[j].key < H.r[j+1].key ) )
++j; // j 为 key 较大的记录的下标
if ( ! ( temp.key < H.r[j].key ) )
break; // temp 应该插入在位置 s 上
H.r[s] = H.r[j]; s = j;
} // for 结束
H.r[s] = temp; // 插入
} // HeapAdjust

void HeapSort ( HeapType &H ) {
// 对顺序表 H 进行堆排序
for ( i = H.length/2; i > 0; --i )
HeapAdjust ( H, i, H.length ); // 把 H.r[1 . . H.length] 构造成堆
for ( i = H.length; i > 1; --i ) {
temp = H.r[1]; H.r[1] = H.r; H.r = temp;
// 将堆顶记录和当前未经排序的子序列 H.r[1 . . i] 中的最后一个记录相互交换
HeapAdjust ( H, 1, i-1 ); // 将 H.r[1 . . i-1] 重新调整为堆
} // for 结束
} HeapSort
 
7. 归并排序算法
typedef SqList RcdType;
void Merge ( RcdType SR[ ], RcdType &T[ ], int i, int m, int n ) {
// 将有序的 SR[i . . m] 和 SR[m+1 . . n] 归并为有序的 TR[i . . n]
for ( j = m+1, k = i; i <= m && j < = n; ++k ) {
// 将 SR 中记录由小到大地并入 TR
if ( SR.key < = SR[j].key ) TR[k] = SR[i++];
else TR[k] = SR[j++];
} // for 结束
if ( i < = m ) TR[k . . n] = SR[i . . m]; // 将剩余的 SR[i . . m] 复制到 TR
if ( j < = n ) TR[k . . n] = SR[j . . n]; // 将剩余的 SR[j . . n] 复制到 TR
} // Merge

void MSort ( RcdType SR[ ], RcdType &TR1[ ], int s, int t ) {
// 将 SR[s . . t] 归并排序为 TR1[s . . t]。
if ( s = = t ) TR1[s] = SR[s];
else {
m = ( s + t ) / 2; // 将SR[s .. t]平分为 SR[s .. m]和SR[m+1 .. t]
MSort ( SR, TR2, s, m ); // 递归地将SR[s .. m]归并为有序的TR2[s .. m]
MSort ( SR, TR2, m+1, t ); // 递归地将SR[m+1.. t]归并为有序的TR2[m+1.. t]
Merge ( TR2, TR1, s, m, t ); // 将TR2[s .. m]和TR2[m+1..t]归并到TR1[s .. t]
} // else 结束
} // MSort

void MergeSort ( SqList &L ) {
// 对顺序表 L 作归并排序。
MSort ( L.r, L.r, 1, L.length );
} // MergeSort
 
8. 基数排序算法
void Distribute ( SLCell &r, int i, ArrType &f, ArrType &e ) {
// 静态链表 L 的 r 域中记录已经按 ( keys[0], keys[1], …, keys[i-1] ) 有序。此算法
// 按第 i 个关键字 keys 建立 RD 个子表,使同一个子表中记录的 keys 相同。
// f[ 0 . . RD-1] 和 e[ 0 . . RD-1] 分别指向各子表中的第一个记录和最后一个记录。
for ( j = 0; j < RD; ++i ) f[j] = 0; // 各子表初始化为空表
for ( p = r[0].next; p; p = r[p].next ) {
j = Ord ( r[p].keys );
// 函数 Ord 将记录中第 i 个关键字映射到 [ 0 . . RD ] 中去
if ( ! f[j] ) f[j] = p;
else r[e[j]].next = p;
e[j] = p; // 将 p 所指的结点插入到第 j 个子表中
} // for 结束
} // Distribute

void Collect ( SLCell &r, int i, ArrType f, ArrType e ) {
// 此算法按 keys 自小至大地将 f[ 0 . . RD-1] 所指各子表依次链接成一个链表。
// e[ 0 . . rd-1] 为各子表的尾指针。
for ( j = 0; ! f[j]; j = Succ(j) ); // 找第一个非空子表,Succ 为求后继函数
r[0].next = f[j]; t = e[j]; // r[0].next 指向第一个非空字表中第一个结点
while ( j < RD-1 ) {
for ( j = Succ(j); j < RD-1 && ! f[j]; j = Succ(j) );
// 寻找下一个非空子表
if ( f[j] ) { r[t].next = f[j]; t = e[j]; } // 链接两个非空字表
} while 结束
r[t].next = 0; // t 指向最后一个非空子表中的最后一个结点
} // Collect

void RadixSort ( SLList &L ) {
// 顺序表 L 采用静态链表表示。对 L 作基数排序,
// 使得 L 成为按关键字自小到大的有序静态链表,L.r[0] 为头结点。
for ( i = 0; i < L.recnum; ++i ) L.r.next = i + 1;
L.r[L.recnum].next = 0; // 将 L 改造为静态链表
for ( i = 0; i < L.keynum; ++i ) {
// 按最低位优先,即 LSD 方法依次对各关键字进行分配和收集
Distribute ( L.r, i, f, e ) // 第 i 趟分配
Collect ( L.r, i, f, e ) // 第 i 趟收集
} // for 结束
} // RadixSort

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值