笔试常考代码段记录

前言

本文记录了一些常见、常考的代码段。

1:将字符串转成数字(atoi实现)

int myint(char *str){
    int ret = 0;
    if(str == NULL){
        return 0;
    }

    while(*str != '\0'){
        ret = ret * 10 + (*str - '0');
        str++;
    }
    return ret;
}

2:将数字转成字符串(sprintf实现)

void reverse(char *str){
    int low = 0;
    int fast = strlen(str) - 1;
    while(low < fast){
        char temp = str[low];
        str[low] = str[fast];
        str[fast] = temp;
        low++;
        fast--;
    }
}

void mystr(int num, char *buf){
    char *head = buf;
    int cnt = 0;
    while(num){
        buf[cnt++] = num % 10 + '0';
        num /= 10;
    }
    reverse(head);
}

3:顺序查找

int seqSearch(int num[], int length, int target){
    int i = 0;
    for(i = 0; i < length && num[i] != target; i++);
    return i == length ? -1 : i;
}

4:二分法实现有序数组数据查找,不在数组内的目标,返回应放入数组的位置

int binarySearch(int num[], int length, int target){
    int low = 0, high = length - 1, mid, ret;
    while(low <= high){
        mid = (low + high) / 2;
        if(num[mid] >= target){
            high = mid - 1;
            ret = mid;
        }
        else{
            low = mid + 1;
        }
    }
    return ret;
}

5:冒泡排序

它通过不断比较相邻的元素,并交换位置,使得较大(或较小)的元素逐渐移动到序列的一端

void swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void bubbleSort(int num[], int length){
    int i, j, flag = 0;
    for(i = 0; i < length - 1; i++){
        for(j = length - 1; j > i; j--){
            if(num[j] < num[j - 1]){
                swap(&num[j], &num[j - 1]);
                flag = 1;
            }
        }
        if(flag == 0){
            return;
        }
    }
}

6:快速排序

首先,选择一个基准元素(一般选择序列中的第一个元素),将序列分为两部分,使得左边的元素都小于基准元素,右边的元素都大于基准元素;然后递归地对左右两部分进行排序,直到整个序列排序完成。

int partition(int num[], int low, int high){
    int pivot = num[low];
    while(low < high){
        while(low < high && num[high] >= pivot) high--;
        num[low] = num[high];
        while(low < high && num[low] <= pivot) low++;
        num[high] = num[low];
    }
    num[low] = pivot;
    return low;
}

void quickSort(int num[], int low, int high){
    int pivotPos = 0;
    if(low < high){
        pivotPos = partition(num, low, high);
        quickSort(num, low, pivotPos - 1);
        quickSort(num, pivotPos + 1, high);
    }
}

7:插入排序

直接插入排序(Straight Insertion Sort): 直接插入排序的思想是将待排序序列分为已排序和未排序两部分,初始时已排序部分只包含第一个元素。然后,依次从未排序部分取出一个元素,插入到已排序部分的适当位置,直到未排序部分为空。

void insertSort(int num[], int length){
    int i, j, temp;
    for(i = 1; i < length; i++){
        temp = num[i];
        for(j = i - 1; j >= 0 && num[j] > temp; j--){
            num[j + 1] = num[j];
        }
        num[j + 1] = temp;
    }
}

8:希尔排序

希尔排序(Shell Sort): 希尔排序是插入排序的一种改进算法,也被称为缩小增量排序。它通过将待排序序列按照一定增量分组,对每个组进行直接插入排序,然后逐渐减小增量,最终将整个序列排序完成。

void shellSort(int num[], int length){
    int i, j, temp, gap;
    for(gap = length / 2; gap > 0; gap /= 2){
        for(i = gap; i < length; i++){
            temp = num[i];
            for(j = i - gap; j >= 0 && num[j] > temp; j -= gap){
                num[j + gap] = num[j];
            }
            num[j + gap] = temp;
        }
    }
}

9:简单选择排序

它的基本思想是每次从待排序序列中选择最小(或最大)的元素,将其放置在已排序序列的末尾

void swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}
void selectSort(int num[], int len){
    int i, j, min;
    for(i = 0; i < len; i++){
        min = i;
        for(j = i + 1; j < len; j++){
            if(num[j] < num[min]){
                min = j;
            }
        }
        if(min != i){
            swap(&num[i], &num[min]);
        }
    }
}

10:堆排序

  1. 构建最大堆:将待排序的数据构建成一个最大堆。最大堆是一种完全二叉树,满足父节点的值大于或等于其子节点的值。通过从最后一个非叶子节点开始,自底向上地对每个非叶子节点进行下沉操作,使得整个树满足最大堆的条件。

  2. 排序:将最大堆的根节点(即最大值)与最后一个叶子节点交换,并将最后一个叶子节点移出堆。然后再对剩余的节点进行下沉操作,重新满足最大堆的条件。重复这个过程,直到堆中只剩下一个节点。

  3. 重复执行步骤2,直到所有的元素都被排序。

#include 
#include 
#include 

int arr[6] = {-1, 8, 54, 13, 23, 2};

void swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void heapAdjust(int num[], int k, int length){
    num[0] = num[k];
    for(int i = 2 * k; i<= length; i *= 2){
        if(i < length && num[i] < num[i + 1]){
            i++;
        }
        if(num[0] > num[i]){
            break;
        }
        else{
            num[k] = num[i];
            k = i;
        }
    }
    num[k] = num[0];
}

void heapSort(int num[], int length){
    for(int i = length / 2; i > 0; i--){
        heapAdjust(num, i, length);
    }
    for(int i = length; i > 1; i--){
        swap(&num[i], &num[1]);
        heapAdjust(num, 1, i - 1);
    }
}
void printfArr(int arr[], int length){
    for(int i = 0; i < length; i++){
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main()
{
    heapSort(arr, 5);
    printfArr(arr + 1, 5);
}

11:软件模拟IIC时序

通用iic文件

#include "iic.h"


void iic_start(void){
   IIC_SDA = 1;
   delay_10us(1);
   IIC_SCL = 1;
   delay_10us(1);
   IIC_SDA = 0;
   delay_10us(1);
   IIC_SCL = 0;
   delay_10us(1);
}

void iic_stop(void){
   IIC_SDA = 0;
   delay_10us(1);
   IIC_SCL = 1;
   delay_10us(1);
   IIC_SDA = 1;
   delay_10us(1);
}

void iic_ack(void){
   IIC_SCL = 0;
   IIC_SDA = 0;
   delay_10us(1);
   IIC_SCL = 1;
   delay_10us(1);
   IIC_SCL = 0;
   delay_10us(1);
}

void iic_nack(void){
   IIC_SCL = 0;
   IIC_SDA = 1;
   delay_10us(1);
   IIC_SCL = 1;
   delay_10us(1);
   IIC_SCL = 0;
   delay_10us(1);

}

u8 iic_wait_ack(void){
   u8 time_cnt = 0;
   IIC_SCL = 0;
   delay_10us(1);
   IIC_SCL = 1;
   delay_10us(1);
   while(IIC_SDA){
      time_cnt++;
      if(time_cnt > 100){
         return 1;
      }
   }
   IIC_SCL = 0;
   delay_10us(1);
   return 0;

}
void iic_write_byte(u8 dat){
   u8 i = 0;
   IIC_SCL = 0;
   for(i = 0; i < 8; i++){
      if((dat & 0x80)){
         IIC_SDA = 1;
      }
      else{
         IIC_SDA = 0;
      }
      dat <<= 1;
      delay_10us(1);
      IIC_SCL = 1;
      delay_10us(1);
      IIC_SCL = 0;
      delay_10us(1);
   }

}

u8 iic_read_byte(u8 ack){
   u8 i = 0, ret = 0;
   for(i = 0; i < 8; i++){
      IIC_SCL = 0;
      delay_10us(1);
      IIC_SCL = 1;
      ret <<= 1;
      if(IIC_SDA){
         ret++;
      }
      delay_10us(1);
   }
   
   if(ack){
      iic_ack();
   }
   else{
      iic_nack();
   }
   return ret;
}


读写at24c02

笔试常考代码段记录_第1张图片

笔试常考代码段记录_第2张图片 

 

#include "24c02.h"
#include "iic.h"


void at24c02_write_one_byte(u8 addr, u8 dat){
   iic_start();
   iic_write_byte(0xA0);
   iic_wait_ack();
   iic_write_byte(addr);
   iic_wait_ack();
   iic_write_byte(dat);
   iic_wait_ack();
   iic_stop();
   delay_ms(10);
}

u8 at24c02_read_one_byte(u8 addr){
   u8 ret = 0;
   iic_start();
   iic_write_byte(0xA0);
   iic_wait_ack();
   iic_write_byte(addr);
   iic_wait_ack();
   iic_write_byte(0xA1);
   iic_wait_ack();
   ret = iic_read_byte(1);
   iic_stop();
   return ret;

}

12:va_list相关用法(可变参)

#include 
#include 

void printNumbers(int count, ...) {
    va_list args;
    va_start(args, count);

    for (int i = 0; i < count; i++) {
        int num = va_arg(args, int);
        printf("%d ", num);
    }
    printf("\n");
    va_end(args);
}

void myprintf(char *fmt, ...){
    va_list args;
    va_start(args, fmt);
    char buf[512];
    vsprintf(buf, fmt, args);
    puts(buf);
    va_end(args);
}

int main() {
    printNumbers(4, 123, 13,42, 234);
    myprintf("%d\n", 24);
    return 0;
}

glibc中printf和scanf函数原型也用到了va_list相关内容

int
printf (const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = vfprintf (stdout, format, arg);
  va_end (arg);

  return done;
}

int
scanf (const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = INTUSE(_IO_vfscanf) (stdin, format, arg, NULL);
  va_end (arg);

  return done;
}

13:字符串匹配算法(BF、KMP) 

BF算法,默认字符串下标从0开始

笔试常考代码段记录_第3张图片

#include 
#include 
#include 

int BF(char* text, char* pattern){
    int i = 0;
    int j = 0;
    int tLen = strlen(text), pLen = strlen(pattern);
    while(i < tLen && j < pLen){
        if(text[i] == pattern[j]){
            i++;
            j++;
        }
        else{
            i = i - j + 1;
            j = 0;
        }
    }
    if(j == pLen){
        return i - j;
    }
    else{
        return -1;
    }
}


int main()
{
    char text[] = "ASDIKOAMD";
    char pattern[] = "AMD";
    int pos = BF(text, pattern);
    char* temp = strstr(text, pattern);
    printf("%c\n", *temp);
    printf("%d\n", pos);
    return 0;
}

KMP算法

#include 
#include 
#include 

// 计算模式串的next数组
void getNext(char* pattern, int* next) {
    int i = 0;  // i为模式串中当前字符的位置
    int j = -1; // j为已匹配的前缀子串的最后一个字符位置
    int len = strlen(pattern);
    next[0] = -1;

    while (i < len) {
        if (j == -1 || pattern[i] == pattern[j]) {
            // 如果j为-1,或当前字符与已匹配的前缀子串的最后一个字符相等
            i++;
            j++;
            next[i] = j;
        } else {
            // 否则,将j指向已匹配的前缀子串的最后一个字符的next值,继续匹配
            j = next[j];
        }
    }
}

// 使用KMP算法进行匹配
int KMP(char* text, char* pattern) {
    int tLen = strlen(text);
    int pLen = strlen(pattern);

    int* next = (int*)malloc(sizeof(int) * (pLen + 1));
    getNext(pattern, next);

    int i = 0;  // i为文本串的当前字符的位置
    int j = 0;  // j为模式串的当前字符的位置

    while (i < tLen && j < pLen) {
        if (j == -1 || text[i] == pattern[j]) {
            // 如果j为-1,或当前字符与模式串的当前字符相等
            i++;
            j++;
        } else {
            // 否则,将j指向模式串中当前字符的next值,继续匹配
            j = next[j];
        }
    }

    free(next);

    if (j == pLen) {
        // 完全匹配,返回在文本串中匹配的起始位置
        return i - j;
    } else {
        // 未找到匹配,返回-1
        return -1;
    }
}

int main() {
    char text[] = "ABABABA";
    char pattern[] = "BAB";
    int pos = KMP(text, pattern);

    if (pos != -1) {
        printf("Pattern found at position: %d\n", pos);
    } else {
        printf("Pattern not found\n");
    }

    return 0;
}

总结

以上就是本文的全部内容了,希望可以帮助到你

你可能感兴趣的:(笔记,排序算法,数据结构,算法,单片机)