c语言课程设计忘备录报告,C语言实现几种常见的算法--备忘录

1.冒泡排序

核心:两两交换----每次遍历会选出最值到两头

//冒泡排序---下面为升序,降序array[j] < array[j + 1]

void bubbleSort(int array[], int count){

for (int i = 0; i < count - 1; i++) {

for (int j = 0; j < count - 1 - i; j++) {

if(array[j] > array[j + 1]) {//升序

array[j] = array[j] + array[j + 1];

array[j + 1] = array[j] - array[j + 1];

array[j] = array[j] - array[j + 1];

}

}

}

}

冒泡排序最好的时间复杂度为O(n)

冒泡排序平均和最坏的时间复杂度为O(n²)

空间复杂度为:O( n )

稳定的排序算法(不会改变相同数原有的先后顺序)

2.选择排序

核心:每次遍历会选出最值到两头-遍历次数依次递减

调用:

int number1[7] = {10, 2, 23, 11, 9, 3, 18};

selectSorts(number1, 7);

//具体实现---下面为升序,降序array[j] > array[min]

void selectSorts(int arr[],int length){

// int temp;

for (int i = 0; i < length - 1; i++) {

int min = i;

for (int j = i+1; j < length; j++) {

if (arr[j] < arr[min]){

min = j;

}

}

if (i != min) {

//不用中间变量交换----相加法

// array[i] = array[i] + array[min];

// array[min] =array[i] - array[min];

// array[i] = array[i] - array[min];

//不用中间变量交换----辗转相除法

array[i] = array[i] ^ array[min];

array[min] =array[i] ^ array[min];

array[i] = array[i] ^ array[min];

//中间变量交换

// temp = array[i];

// array[i] = array[min];

// array[min] = temp;

}

}

}

时间/空间复杂度---平均和最坏的都是O(n²)

不稳定的排序方法

3.快速排序

核心:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,

然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以[递归]进行,以此达到整个数据变成有序[序列](https://baike.baidu.com/item/%E5%BA%8F%E5%88%97/1302588)。

/*快速排序*/

void Qsort(int a[],int low ,int high)

{

if(low>=high)

return ;

printf("start:%d end:%d\n",low,high) ;

int first = low ;

int last = high ;

int key = a[low] ;

while(first

{

while(first=key)

--last ;

a[first] = a[last] ;

while(first

++first ;

a[last] = a[first] ;

}

a[first] = key ;

Qsort(a,low,first-1) ;

Qsort(a,first+1,high) ;

}

最好和平均的时间复杂度为O(nlogn)

最坏的时间复杂度为O(n²)

最优空间复杂度 longn

最差空间复杂度为:O( n )

4.直接插入排序

核心:两层for循环;外层每次先找到那个比前面值都小(升序)或都大(降序)的指,并做标记;

内层for循环将比它大的值依次后移;然后再将标记的值赋值给内层循环最小标记的下标+1出做替换

void strightINsertSort(int arr[], int count){

for (int i = 1; i < count; i ++) {

if (arr[i - 1] > arr[i]) {

int temp = arr[i];

int j;

for (j = i - 1; j >= 0 && arr[j] > temp; j --) {

arr[j+1] = arr[j];

}

arr[j + 1] = temp;

}

}

}

最好情况(初始情况就是正序)下时间复杂度是O(n)

平均情况和最坏情况时间复杂度是O(n²)

5.二分插入排序

核心:是在插入第i个元素时,对前面的0~i-1元素进行折半,先跟他们中间的那个元素比,

如果小,则对前半再进行折半,否则对后半进行折半,

直到left>right,然后再把第i个元素前1位与目标位置之间的所有元素后移,再把第i个元素放在目标位置上。

void binaryInsertSort(int arr[], int count){

for (int i = 1; i < count; i ++) {

if (arr[i] < arr[i - 1]) {

int temp = arr[i];

int left = 0;

int right = i - 1;

while (left <= right) {

int center = (left + right)/2;

if (arr[center] <= temp) {

left = center + 1;

}else{

right = center - 1;

}

}

for (int j = i; j > left; j --) {

arr[j] = arr[j - 1];

}

arr[left] = temp;

}

}

}

最好的时间复杂度O(logn)。

最坏和平均时间复杂度O(n^2)。

稳定的排序算法

6.堆排序

ef6795aa5aa8

原理动图----引用于七巧板子博主

核心: 初始化大顶堆时 是从最后一个有子节点开始往上调整最大堆。而堆顶元素(最大数)与堆最后一个数交换后,需再次调整成大顶堆,此时是从上往下调整的。

不管是初始大顶堆的从下往上调整,还是堆顶堆尾元素交换,每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换,

交换之后都可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整。

在算法中是用一个while循环来解决

//最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点

void maxHeapify(int numbers[], int start, int end) {

//建立父节点指标和子节点指标

int dad = start;

int son = dad * 2 + 1;

while (son <= end) { //若子节点指标在范围内才做比较

if (son + 1 <= end && numbers[son] < numbers[son + 1]) { //先比较两个子节点大小,选择最大的

son++;

}

if (numbers[dad] > numbers[son]) {//如果父节点大于子节点代表调整完毕,直接跳出函数

return;

}else { //否则交换父子内容再继续子节点和孙节点比较

int temp = numbers[son];

numbers[son] = numbers[dad];

numbers[dad] = temp;

dad = son;

son = dad * 2 + 1;

}

}

}

/**堆排序(HeapSort):

1、首先从最后一个父节点做最大堆调整,找出最大值,此时最大值位于根节点

2、然后将最大值和已排好元素(依次找出的最大值排出的序列,如:6 3 9 23 12 8 [15 16 17 18])前一位元素交换位置,再将除已排好元素外的其他元素(6 3 9 23 12 8)做最大堆调整,找出最大值,此时最大值位于根节点

3、重复步骤2,直至结束

*/

void heapSort(int numbers[], int length) {

//1.初始化堆(子节点-->根节点),i从最後一个父节点开始做最大堆调整,调整结束后根节点得到最大值

for (int i = length / 2 - 1; i >= 0; i--) {

maxHeapify(numbers, i, length - 1);

}

//2.(根节点-->子节点)先将第一个元素和已排好元素前一位做交换,再重新调整,直到排序完毕

for (int i = length - 1; i > 0; i--) {

int temp = numbers[0];

numbers[0] = numbers[i];

numbers[i] = temp;

maxHeapify(numbers, 0, i - 1);

}

}

最好、最坏和平均时间复杂度都为O(nlogn)。

不稳定排序算法

7.归并排序

核心:该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

若将两个有序表合并成一个有序表,称为二路[归并]

>>从上往下-->步骤

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾

将另一序列剩下的所有元素直接复制到合并序列尾

//合并

void merge(int a[], int start, int mid, int end) {

int *temp = (int *)malloc((end - start + 1) * sizeof(int)); // tmp是汇总2个有序区的临时区域

int i = start; // 第1个有序区的起始索引

int j = mid + 1; // 第2个有序区的起始索引

int k = 0; // 临时区域的索引

while(i <= mid && j <= end) {

if (a[i] <= a[j]) {

temp[k++] = a[i++];

}else {

temp[k++] = a[j++];

}

}

while(i <= mid) {

temp[k++] = a[i++];

}

while(j <= end) {

temp[k++] = a[j++];

}

// 将排序后的元素,全部都整合到数组a中。

for (i = 0; i < k; i++) {

a[start + i] = temp[i];

}

free(temp);

}

/*

* 归并排序(从上往下)

*

* 参数说明:

* a -- 待排序的数组

* start -- 数组的起始地址

* endi -- 数组的结束地址

*/

void mergeSortUpToDown(int a[], int start, int end) {

if(a == NULL || start >= end) {

return ;

}

int mid = (end + start) / 2;

mergeSortUpToDown(a, start, mid); //递归排序a[start...mid]

mergeSortUpToDown(a, mid + 1, end); //递归排序a[mid + 1...end]

// a[start...mid] 和 a[mid...end]是两个有序空间,

// 将它们排序成一个有序空间a[start...end]

merge(a, start, mid, end);

}

最好、最坏和平均时间复杂度均为O(nlogn)。

稳定的排序算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值