预定义
#define Ty int // 以整型为例
交换数据的函数
void swap(Ty* elems,int i,int j) {
Ty temp=elems[i];
elems[i]=elems[j];
elems[j]=temp;
}
// 如果确认只用整型数据使用下面的代码会更快,因为减少了函数压栈,也使用了位运算
#define SWAP_INT(a, b) \
{ \
a = (a) ^ (b); \
b = (a) ^ (b); \
a = (a) ^ (b); \
}
原理:将一段序列的最大值(最小值)拿到最左边或者最右边的操作,使用循环重复操作,(每轮排序都会少一个最大值或最小值),当最后只剩下一个数据的时候整个序列就已经排好序了。
冒泡排序的原理很简单,使用代码实现也很简单。也是所有排序算法里面最简单的一个。
具体代码实现:
void bubSort(Ty* elems,int size) {
for (int i = 0;i < size;size--) { //轮
for (int j = i + 1;j < size;j++) { //找剩余元素中的最值
if (elems[j] < elems[j-1]) {
swap(elems,j,j-1);
}
}
}
}
void bubSort(Ty* elems,int size) {
for(int i=0;i<size-1;i++)
for(int j=i+1;j<size;j++)
if(elems[i]<elems[j])
swap(elems,i,j);
}
直接使用两层循环去实现,外层循环主要作用是存放最大值或最小值的,内存循环的主要作用是找到发生冲突的元素,如果发生冲突就交换两个数据。当两层循环的结束的时候整个序列就自然排好序了。时间复杂度为O(n^2).
原理:基本思想和冒泡排序是一样的,选择排序相对于冒泡排序的优点就是减少交换次数。算法思想都是在序列中找到最大值(最小值),然后存放好下次进入循环就访问不到这个最大值(最小值)。当两层循环都结束的时候序列就自然排好了。
具体代码实现:
void selectSort(Ty* elems,int size) {
for(int i=0;i<size-1;i++) {
int minPos=i;
for(int j=i+1;j<size;j++)
if(elems[minPos]>elems[j])
minpos=j;
swap(elems,i,minPos);
}
}
原理:基本思想还是冒泡排序,不过插入排序是两边相靠的冒泡,所以在序列部分有序的情况下,插入排序的效率要比冒泡排序效率高。从序列的尾部开始往前比较,如果当前的数据小于(大于)前一个的数据就进行交换,否则进入下一次循环,直到外层循环遍历完整个序列就自然排好序了。
具体代码实现:
//使用交换函数
void insertSort(Ty* elems,int size) {
for(int i = 1;i < size;i++)
for(int j = i;j > 0 && elems[j-1] > elems[j];j--)
swap(elems,j-1,j);
}
//不使用交换函数
void insertSort(Ty* elems,int size) {
for (int i = 1;i < size;i++) {
int j = i;
int temp = arr[j];
for (;j >= 1 && temp < arr[j-1];j--)
arr[j] = arr[j-1];
arr[j] = temp;
}
}
原理:希尔排序是建立在插入排序的基础上进行优化的排序算法,所以希尔排序又叫做优化版的插入排序。
代码实现:
void shellSort(Ty* elems,int size) {
for(int h = 4;h >= 1;h = h >> 1)
for(int i = h;i < size;i++)
for(int j = i;j >= h && elems[j] > elems[j-h];j -= h)
swap(elems,j,j-h);
}
//使用交换函数
void shellSort(Ty* elems,int size) {
int h = 1;
while(h < size/3) h = 3*h + 1;
while(h >= 1) {
for(int i = h;i < size;i++)
for(int j = i;j >= h && elems[j] > elems[j-h];j -= h)
swap(elems,j,j-h);
h /= 3;
}
}
//不使用交换函数
void shellSort(Ty* elems,int size) {
int h = 1;
int t = length/3;
while (h < t) h = 3*h + 1;
while (h >= 1) {
for (int i = h;i < length;i++) {
int j = h;
Ty temp = arr[j];
for (;j >= h && temp < arr[j-h];j-=h)
arr[j] = arr[j-h];
arr[j] = temp;
}
h /= 3;
}
}
# 实例解释
size=13,h=4 # h=13/3
h
|
4 6 8 7 9 5 3 1 2 10 0 11 12
||
ij
# 4<9 so i++;j=i
h
|
4 6 8 7 9 5 3 1 2 10 0 11 12
||
ij
# 6>5 交换 j-=h
h
|
4 5 8 7 9 6 3 1 2 10 0 11 12
| |
j i
# j<h i++;j=i
# 依此类推
原理:快速排序的核心思想是设立一个轴,然后其他数据都和这个轴作比较,最后把轴放在序列的中间,执行完一遍快速排序后左边的数据都比轴小,右边的数据都比轴大。然后递归下去,当递归结束的时候就拍好序了。快速排序的排序很快,但是当数据形成一边倒的情况的时候就发挥不出快速排序的优势。
具体代码实现:
//稍微修改一下适用于单链表的快速排序
void quickSort(Ty *elems, int first, int last) {
if (first >= last || first < 0 || last < 0)
return;
Ty privot = elems[first];
int i = first + 1;
int j = first + 1;
while (j <= last) {
if (elems[j] < privot) {
swap(&elems[i], &elems[j]);
i++;
}
j++;
}
swap(&elems[first], &elems[i - 1]);
quickSort(elems, first, i - 1);
quickSort(elems, i, last);
}
//仅仅适用于数组的快速排序
void quickSort(Ty* elems,int left,int right) {
if (left >= right) return;
int i = left;
int j = right;
Ty privot = elems[i];
while (i < j) {
while (i < j && arr[j] >= privot) --j;
arr[i] = arr[j];
while (i < j && arr[i] <= privot) ++i;
arr[j] = arr[i];
}
arr[i] = privot;
quickSort(elems,left,i - 1);
quickSort(elems,i + 1,right);
}
原理:把要排序的序列拆分成多个含有一个数据的序列,然后按照从小到大(从大到小)进行合并,这样就自然的将无序的序列排好序。
具体代码实现:
void merge(int arr[],int left,int mid,int right,int* temp) {
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right) temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
while (i <= mid) temp[k++] = arr[i++];
while (j <= right) temp[k++] = arr[j++];
for (i = left;i <= right;i++)
arr[i] = temp[i];
}
void merge_sort(int arr[],int left,int right,int* temp) {
if (left >= right) return;
int mid = left + ((right - left) >> 1);
merge_sort(arr,left,mid,temp);
merge_sort(arr,mid + 1,right,temp);
merge(arr,left,mid,right,temp);
}
void mergeSort(int arr[],int length) {
int* temp = (int*)malloc(sizeof(int)*length);
assert(temp);
merge_sort(arr,0,length - 1,temp);
free(temp);
}
堆分有小顶堆和大顶堆,而堆排序又分有外堆和内堆。
外堆
意思是,而外申请一段和原来数组一样大的内存大小,并将数组的元素构造成小顶堆或大顶堆。根据排序的顺序和逆序确定要构成的堆结构是大顶堆还是小顶堆。现以最终序列是顺序排序(从小到大)为例,则需要构成的堆结构是小顶堆。因为小顶堆可以快速的找到序列的最小值,如果将小顶堆的数据依次弹出,则每次弹的都是剩余序列的最小值,并且每次弹出就放到原来的数组中,当小顶堆里的数据都弹出来完了,原来的数组也自然有序了。如果要求最终序列是逆序的则构造的堆结构是大顶堆,然后操作是一样的。时间复杂度是\(O(nlogn)\). 空间复杂度是\(O(n)\).
内堆
意思是,不需要额外申请空间,直接在原来的数组上进行操作。现以最终序列是顺序排序(从小到大)为例,则需要构成的堆结构是大顶堆。在原来的数组上构造堆结构称之为 “堆化” ,heapify.形成大顶堆后,将堆顶依次弹出并立即放数组的尾部,反复操作此步骤直到最后一个数据,最终自然形成从小到大依次排好序。
//外堆
//堆的结构体描述
typedef struct Heap {
Ty* root;
int size;
}Heap;
//创建堆内存
Heap* creatHeap(int capacity) {
Heap* heap = (Heap*)malloc(sizeof(Heap));
assert(heap);
heap->root = (Ty*)malloc(sizeof(Ty) * (capacity+1) );
heap->size = 1;
return heap;
}
//入堆
//先将要插入的数据插入到堆的尾部,然后向上渗透,爬到对应的位置,就把数据放进去即可
void pushHeap(Heap* heap,Ty data) {
int current = heap->size++;
int parent = current >> 1;
heap->root[current] = data;
while (parent) {
if (heap->root[current] < heap->root[parent]) {
swap(heap->root,current,parent);
current = parent;
parent >>= 1;
}
else break;
}
}
//出堆
//先将堆顶元素保存下来,然后使用堆的尾部覆盖堆顶,然后往下渗透,走到对应的位置,就把数据放进去,然后返回保存的元素
Ty popHeap(Heap* heap) {
int current = 1;
int rchild = 3;
int n = --heap->size;
Ty ret = heap->root[1];
heap->root[1] = heap->root[n];
while (rchild < n) {
int small = heap->root[rchild - 1] < heap->root[rchild] ? rchild - 1 : rchild;
if (heap->root[small] < heap->root[current]) {
swap(heap->root,current,small);
current = small;
rchild = (current << 1) + 1;
}
else break;
}
return ret;
}
//内堆
//在原来数组的基础上直接操作,其实就是入堆和出队直接结合,不需要额外申请空间
void heapify(int arr[],int current,int length) {
int rchild = (current << 1) + 2;
int large;
while (rchild <= length && (arr[large = rchild == length ? rchild-1 : (arr[rchild-1] > arr[rchild] ? rchild-1 : rchild)] > arr[current])) {
swap(arr,large,current);
current = large;
rchild = (current << 1) + 2;
}
}
void heapSort(int arr[],int length) {
int current = length >> 1;
while (current >= 0) heapify(arr,current--,length);
while (length) {
swap(arr,0,--length);
heapify(arr,0,length);
}
}
前面的算法都是基于比较的排序,计数排序是利用了数组的下标天然有序原理进行排序,所以计数排序是基于统计而排序的排序算法。算法的核心思想是遍历一个无序数组,将遍历到的数据按它的数值找到统计数组的对应下标将其放入统计数组中,依次类推,直到无序的数组的每一个数据都被遍历完之后统计数组也已经初始化完毕,接下来就是遍历统计数组如果遍历到的空间是大于零的就将其下标存入原来的数组中,直到统计数组被遍历完,最终可以排好序。
void countSort(int arr[],int length,int max) {
int* count = (int*)calloc(max,sizeof(int));
for (int i = 0;i < length;i++) {
count[arr[i]]++;
}
for (int i = 0,j = 0;i < max;i++) {
while (count[i]--)
arr[j++] = i;
}
free(count);
}
桶排序的思想,按照数字的位数进行排序,准备0-9的链式队列,从低位开始到高位进行排序,当最高位被排好序后原来的序列自然排好序了。
例如:对以下序列进行基数排序
578,234,86,432,512,618,384
排序过程:
第一轮(\(在第零轮的基础上按10^0位排\)):432,512,234,384,86,578,618
第二轮(\(在第一轮的基础上按10^1位排\)):512,618,432,234,578,384,86
第三轮(\(在第二轮的基础上按10^2位排\)):86,234,384,432,512,578,618
第三轮结束序列自然排好序。86不够3位数,就往前面补零,即86 = 086.
void redixSort(int arr[], int length) {
int i;
int j;
int ii;
int jj;
int temp[10][10];
for (ii = 0; ii < 10; ii++)
for (jj = 0; jj < 10; jj++)
temp[ii][jj] = -1;
for (int k = 10; k < 10000; k *= 10) {
for (i = 0; i < length; i++) {
int index = (arr[i] % k) / (k / 10);
j = 0;
while (temp[index][j] != -1)
j++;
temp[index][j] = arr[i];
}
i = 0;
for (ii = 0; ii < 10; ii++) {
for (jj = 0; jj < length && temp[ii][jj] != -1; jj++) {
arr[i++] = temp[ii][jj];
temp[ii][jj] = -1;
}
}
}
}
我在去年已经先将视频讲解发布到B站上了,但是当时没有将文档发布,直接放到博客里让大家访问和学习吧。下面是本次内容的视频链接:
B站视频链接:Cukor丘克
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类
我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night
我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我
我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果
我有一个对象如下:[{:id=>2,:fname=>"Ron",:lname=>"XXXXX",:photo=>"XXX"},{:id=>3,:fname=>"Dain",:lname=>"XXXX",:photo=>"XXXXXXX"},{:id=>1,:fname=>"Bob",:lname=>"XXXXXX",:photo=>"XXXX"}]我想按fname排序,不区分大小写,所以它会导致编号:1,3,2我该如何排序?我正在尝试:@people.sort!{|x,y|y[:fname]x[:fname]}但这没有任何效果。 最佳答案
有人可以告诉我如何根据自定义字符串对嵌套数组进行排序吗?比如有没有办法排序:[['Red','Blue'],['Green','Orange'],['Purple','Yellow']]“橙色”、“黄色”,然后是“蓝色”?最终结果如下所示:[['Green','Orange'],['Purple','Yellow'],['Red','Blue']]它不是按字母顺序排序的。我很想知道我是否可以定义要排序的值以实现上述目标。 最佳答案 sort_by对于这种排序总是非常方便:a=[['Red','Blue'],['Green','Ora
我有以下现有的Dog对象数组,它们按age属性排序:classDogattr_accessor:agedefinitialize(age)@age=ageendenddogs=[Dog.new(1),Dog.new(4),Dog.new(10)]我现在想插入一条新的狗记录,并将它放在数组中的正确位置。假设我想插入这个对象:another_dog=Dog.new(8)我想把它插入到数组中,让它成为数组中的第三项。这是一个人为的示例,旨在演示我特别想如何将一个项目插入到现有的有序数组中。我意识到我可以创建一个全新的数组并重新对所有对象进行排序,但这不是我的目标。谢谢!