今天看了C++之父写的C++程序设计,对于其中的shell排序有了一个比较好的认识,记录下来以便日后复习
shell排序用到了分组和插入排序的方法
例如有个数组{5, 6, 3,2,1, 4}
首先先分组,以数组的长度n / 2 = 3
这样就分为了{5,2} {6,1} {3,4} 注意每组的元素为数组元素每间隔n/2个元素之后的那个元素 比如5, 之后应该是2,依次类推
然后每组进行插入排序得到{2, 5} {1, 6} {3,4}
注意代码所体现的插入排序的顺序是:如果每组是{5, 3, 2} {6, 1, 4} {3, 4, 5} 那么他会先以3进行插入之后 会跳到第二组以1进行第二组的插入,之后是第三组 然后在返回第一组以2进行插入依次类推
然后3/2=1 这样就分为了1组也就是全部{2,5,1, 6, 3, 4}进行插入排序最后得到{1, 2, 3, 4, 5, 6}
以C++之父所写的运用代码
int cmp1(void *, void *);
int cmp2(void *, void *);
//shell排序的运用
typedef int (*CFT)(const void *, const void *);
void ssort(void *base, size_t n, size_t sz, CFT cmp)
{
/*对向量base的n个元素进行递增排序
用由‘cmp’所指的函数进行比较
元素的大小为sz
*/
for (int grap = n / 2; grap > 0; grap /= 2)
{
for (int i = grap; i < n; i++)
{
for (int j = i - grap; j >= 0; j -= grap)
{
char *b = static_cast<char *>(base);
char *pj = b + j * sz;
char *pjg = pj + grap * sz;
if (cmp(pjg, pj) < 0)
{
for (int k = 0; k < sz; k++)
{
char temp = pj[k];
pj[k] = pjg[k];
pjg[k] = temp;
}
}
}
}
}
}
struct User {
char *name;
char *id;
int dept;
};
User heads[] = {
"Ritchie D.M.", "dmr", 11271,
"Sethi R.", "ravi", 11272,
"Szymanski T.G.", "tgs", 11273,
"Schryer N.L.", "nls", 11274,
"Scheyer N.L.", "nls", 11275,
"Kernigham B.W.", "bwk", 11276
};
void print_id(User *v, int n)
{
for (int i = 0; i < n; i++)
cout << v[i].name << '\t' << v[i].id << '\t' << v[i].dept << '\n';
}
int cmp1(const void *p, const void *q) //比较名字字串
{
return strcmp(static_cast<const User*>(p)->name,
static_cast<const User*>(q)->name);
}
int cmp2(const void *p, const void *q) //比较部门
{
return static_cast<const User*>(p)->dept -
static_cast<const User*>(q)->dept;
}