C语言模版(机试666)
实现空格输入
//c语言int i=0;while(scanf("%c",&s[i])!=EOF){//多组输入if(s[i]!='\n') ++i;else {int len=i;i=0;}}int i=0;while(scanf("%c",&s[i])&&s[i]!='\n'){//单组输入++i;}int len=i;i=0;printf("%s\n",s);
gcd
int gcd(int a,int b){return b?gcd(b,a%b):a;
}
素数
//素数打表
prim[1]=1;
for(int i=2;i*i<TOP;++i)if(!prim[i])for(int j=i*i;j<TOP;j+=i)prim[j]=1;
快排
void quick_sort(int q[], int l, int r){if(l >= r) return ;int x = q[l], i = l - 1, j = r + 1;while(i < j) {do i++; while(q[i] < x);do j--; while(q[j] > x);if(i < j) swap(q[i], q[j]);}quick_sort(q, l, j);quick_sort(q, j + 1, r);
}
hash开放寻址法
#include <stdio.h>const int N = 2*1e5 + 3, NU = 0x3f3f3f3f; // N为指数,NU为NULL标记
int h[N]; // 数组存储int find(int x){int t = (x % N + N) % N;while(h[t] != NU && h[t] != x){ // 当所找的当前位置不为NULL并且也不是x时,继续向后查找t = t + 1 % N; // 查到N时,再重头开始查}return t; // 返回的t为空位置的下标或目标元素的下标
}int main(){int m; scanf("%d", &m);for(int i = 0; i <= N; i++) h[i] = NU;while(m--){char op[2]; scanf("%s", op);int x; scanf("%d", &x);if(*op == 'I') h[find(x)] = x; //将x赋值给h中的空位置下标else{ if(h[find(x)] == x) puts("Yes"); // 若该下标对应的数为x,则查找成功else puts("No"); // 若为NU说明不存在该数}}return 0;
}
堆
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int HPDataType;
typedef struct Heap {HPDataType* a;int size;int capacity;
}HP;//堆的初始化
void HPInit(HP* php) {php->a = NULL;php->size = php->capacity = 0;
}//堆的销毁
void HPDestory(HP* php) {assert(php);free(php->a);php->size = php->capacity = 0;
}//交换函数
void swap(int* px, int* py) {int a = *px;*px = *py;*py = a;
}//堆的向上调整
void AdjustUp(HPDataType*a, int child) {//注意没有HP*phpint parent = (child - 1) / 2;//while(parent>=0)while (child > 0) {if (a[child] > a[parent]) {swap(&a[child], &a[parent]);child = parent;parent = (parent - 1) / 2;}else {break;}}
}//堆的创建
void HPPush(HP* php, HPDataType x) {assert(php);if (php->capacity == php->size) {int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;HPDataType* tmp = realloc(php->a, sizeof(HPDataType) * newCapacity);if (tmp == NULL) {//tmp == NULLperror("realloc fail");return;}php->a = tmp;php->capacity = newCapacity;}php->a[php->size] = x;//注意php->size++;AdjustUp(php->a, php->size - 1);//注意
}//取堆顶元素
HPDataType HPTop(HP* php) {assert(php);return php->a[0];
}//向下调整算法
void AdjustDown(HPDataType* a,int size, int parent) {int child = parent * 2 + 1;while (child < size) {if (child + 1 < size && a[child + 1] > a[child]) {child++;}if (a[child] > a[parent]) {swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else {break;}}
}//堆的头删
void HPPop(HP* php) {assert(php);assert(php->size > 0);//注意swap(&php->a[0], &php->a[php->size - 1]);php->size--;//头删 ↓此处不能为php->a[0],是parent的下标AdjustDown(php->a, php->size,0);
}//堆的判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}int main() {HP hp;int a[11] = { 34,74,14,20,30,50,82,68,30,72,55 };HPInit(&hp);//记得初始化for (int i = 0; i < 11; i++) {HPPush(&hp, a[i]);}for (int i = 0; i < 11; i++) {printf("%d ", hp.a[i]);}printf("\n");HPPop(&hp);printf("%d", HPTop(&hp));HPPop(&hp);printf("\n");printf("%d", HPTop(&hp));printf("\n");for (int i = 0; i < 9; i++) {printf("%d ", hp.a[i]);}return 0;
}
字符串哈希
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, P = 131;
typedef unsigned long long ULL;
ULL h[N], p[N];
int l1, r1, l2, r2, n, m;
char str[N];
ULL find(int l, int r)
{return h[r] - h[l-1] * p[r-l+1];
}
int main()
{scanf("%d%d%s", &n, &m, str+1);p[0] = 1;for(int i = 1; i <= n; i ++ ){p[i] = p[i-1] * P;h[i] = h[i-1] * P + str[i];}while(m -- ){scanf("%d%d%d%d", &l1, &r1, &l2, &r2);if(find(l1, r1) == find(l2, r2)) puts("Yes");else puts("No");}return 0;
}
C语言的常用的标准头文件有 :
<ctype.h> <time.h> <stdio.h>
<stdlib.h> <math.h> <string.h>
函数原型 | 功能 |
---|---|
int iscntrl(int c) | 判断字符c是否为控制字符**。 |
int isalnum(int c) | 判断字符c是否为字母或数字 |
int isalpha(int c) | 判断字符c是否为英文字母 |
int isascii(int c) | 判断字符c是否为ASCII码** |
int isblank(int c) | 判断字符c是否为TAB或空格 |
int isdigit(int c) | 判断字符c是否为数字 |
int isgraph(int c) | 判断字符c是否为除空格外的可打印字符 |
int islower(int c) | 判断字符c是否为小写英文字母 |
int isprint(int c) | 判断字符c是否为可打印字符(含空格) |
int ispunct(int c) | 判断字符c是否为标点符号 |
int isspace(int c) | 判断字符c是否为空白符 |
int isupper(int c) | 判断字符c是否为大写英文字母 |
int isxdigit(int c) | 判断字符c是否为十六进制**数字 |
int toascii(int c) | 将字符c转换为ASCII码 |
int tolower(int c) | 将字符c转换为小写英文字母 |
int toupper(int c); | 将字符c转换为大写英文字母 |
函数原型 | 功能 |
---|---|
float fabs(float x) | 求浮点数x的绝对值 |
int abs(int x) | 求整数x的绝对值 |
float acos(float x) | 求反余弦值 |
float asin(float x) | 求反正弦值 |
float atan(float x) | 求反正切值 |
float atan2(float y,float x) | 求y/x 的反正切值 |
float ceil(float x) | 求不小于x的最小整数 |
float cos(float x) | 求余弦值 |
float cosh(float x) | 求双曲余弦值 |
float exp(float x) | 求e的x次幂 |
float floor(float x) | 求不大于x的最大整数 |
float fmod(float x, float y) | 计算x/y的余数 |
float frexp(float x, int *exp) | 把浮点数x分解成尾数和指数 |
float ldexp(float x, int exp) | 返回x*2^exp的值 |
float log(float x) | 计算自然对数 |
float log10(float x) | 计算常用对数 |
float pow(float x, float y) | 计算x的y次幂 |
float sin(float x) | 计算正弦值 |
float sinh(float x) | 计算双曲正弦值 |
float sqrt(float x) | 计算平方根 |
float tan(float x); | 计算正切值 |
float tanh(float x) | 求双曲正切值 |
函数原型 | 功能 |
---|---|
int printf(char *format…) | 产生格式化输出的函数 |
int getchar(void) | 从键盘上读取一个键, 并返回该键的键值 |
int putchar(char c) | 在屏幕上显示字符c |
FILE *fopen(char *filename, char *type) | 打开一个文件 |
FILE *freopen(char *filename, char *type, FILE *fp) | 打开一个文件, 并将该文件关联到fp指定的流 |
int fflush(FILE *stream) | 清除一个流 |
int fclose(FILE *stream) | 关闭一个文件 |
int remove(char *filename) | 删除一个文件 |
int rename(char *oldname, char *newname) | 重命名文件 |
FILE *tmpfile(void) | 以二进制+方式打开暂存文件 |
char *tmpnam(char *spttr) | 创建一个唯一的文件名† |
int setvbuf(FILE *stream, char *buf, int type, unsigned size) | 把缓冲区与流相关 |
int fprintf(FILE *stream, char *format[, argument,…]) | 传递格式化输出到一个流中 |
int scanf(char *format[argument,…]) | 执行格式化输入 |
int fscanf(FILE *stream, char *format[,argument…]) | 从一个流中执行格式化输入 |
int fgetc(FILE *stream) | 从流中读取字符 |
char *fgets(char *string, int n, FILE *stream) | 从流中读取一字符串 |
int fputc(int ch, FILE *stream) | 送一个字符到一个流中 |
int fputs(char *string, FILE *stream) | 送一个字符串到一个流中 |
int getc(FILE *stream) | 从流中取字符 |
int getchar(void) | 从 stdin 流中读字符 |
char *gets(char *string) | 从流中取一字符串 |
int putchar(int ch) | 在 stdout 上输出字符 |
int puts(char *string) | 送一字符串到流中 |
int ungetc(char c, FILE *stream) | 把一个字符退回到输入流中 |
int fread(void *ptr, int size, int nitems, FILE *stream) | 从一个流中读数据 |
int fwrite(void *ptr, int size, int nitems, FILE *stream) | 写内容到流中 |
int fseek(FILE *stream, long offset, int fromwhere) | 重定位流上的文件指针† |
long ftell(FILE *stream) | 返回当前文件指针 |
int rewind(FILE *stream) | 将文件指针重新指向一个流的开始 |
int fgetpos(FILE *stream) | 取得当前文件的句柄 |
int fsetpos(FILE *stream, const fpos_t *pos) | 定位流上的文件指针 |
void clearerr(FILE *stream) | 复位错误标志 |
int feof(FILE *stream) | 检测流上的文件结束符 |
int ferror(FILE *stream) | 检测流上的错误 |
void perror(char *string) | 系统错误信息 |
函数原型 | 功能 |
---|---|
char *itoa(int i) | 把整数i转换成字符串 |
void exit(int retvaI) | 结束程序 |
double atof(const char *s) | 将字符串s转换为double类型 |
int atoi(const char *s) | 将字符串s转换为int类型 |
long atol(const char *s) | 将字符串s转换为long类型 |
double strtod (const char*,char **endp) | 将字符串s前缀转换为double型 |
long strtol(const char*s,char **endp,int base) | 将字符串s前缀转换为long型 |
unsined long strtoul(const char*s,char **endp,int base) | 将字符串s前缀转换为unsined long型 |
int rand(void) | 产生一个0~RAND_MAX之间的伪随机数* |
void srand(unsigned int seed) | 初始化随机数发生器* |
void *calloc(size_t nelm, size_t elsize) | 分配主存储器 |
void *malloc(unsigned size) | 内存分配函数 |
void *realloc(void *ptr,unsigned newsize) | 重新分配主字 |
void free(void *ptr) | 释放已分配的块 |
void abort(void) | 异常终止一个进程 |
void exit(int status) | 终止应用程序 |
int atexit(atexit_t func) | 注册终止函数 |
char *getenv(char *envvar) | 从环境中取字符串 |
void *bsearch(const void *key,const void *base,size_t *nlem,size_t width,int(*fcmp)(const void *, const *) ) | 二分法搜索函数 |
void qsort(void *base,int nelm,int width, int (*fcmp)( )) | 使用快速排序例程进行排序 |
int abs(int i) | 求整数的绝对值 |
long labs(long n) | 取长整型绝对值 |
div_t div(int number, int denom) | 将两个整数相除,返回商和余数 |
ldiv_t ldiv(long Inumber,long ldenom) | 两个长整型数相除,返回商和余数 |
函数原型 | 功能 |
---|---|
clock_t clock(void); | 确定处理器时间函数 |
time_t time(time_t *tp); | 返回当前日历时间 |
double difftime(time_t time2, time_t time1); | 计算两个时刻之间的时间差 |
time_t mktime(struct tm *tp); | 将分段时间值转换为日历时间值 |
char *asctime(const struct tm *block); | 转换日期和时间为ASCII码 |
char *ctime(const time_t *timer); | 把日期和时间转换为字符串 |
struct tm *gmtime(const time_t *timer); | 把日期和时间转换为格林尼治标准时间 |
struct tm *localtime(const time_t *timer); | 把日期和时间转变为结构 |
size_t strftime(char *s, size_t smax, const char *fmt, const struct tm *tp); | 根据fmt的格式要求将*tp中的日期与时间转换为指定格式 |
函数原型 | 功能 |
---|---|
int bcmp(const void *s1, const void *s2, int n) | 比较字符串s1和s2的前n个字节是否相等 |
void bcopy(const void *src, void *dest, int n) | 将字符串src的前n个字节复制到dest中 |
void *bzero(void *s, int n) | 置字节字符串s的前n个字节为零 |
void *memccpy(void *dest, void *src, unsigned char ch, unsigned int count) | 由src所指内存区域复制不多于count个字节到dest所指内存区域,如果遇到字符ch则停止复制 |
void *memcpy(void *dest, void *src, unsigned int count) | 由src所指内存区域复制count个字节到dest所指内存区域 |
void *memchr(void *buf, char ch, unsigned int n) | 从buf所指内存区域的前count个字节查找字符ch |
int memcmp(void *buf1, void *buf2, unsigned int count) | 比较内存区域buf1和buf2的前count个字节 |
int memicmp(void *buf1, void *buf2, unsigned int count) | 比较内存区域buf1和buf2的前count个字节但不区分字母的大小写 |
void *memmove(void *dest, const void *src, unsigned int count) | 由src所指内存区域复制count个字节到dest所指内存区域 |
void *memset(void *buffer, int c, int count) | 把buffer所指内存区域的前count个字节设置成字符c |
void setmem(void *buf, unsigned int count, char ch) | 把buf所指内存区域前count个字节设置成字符ch |
void movmem(void *src, void *dest, unsigned int count) | 由src所指内存区域复制count个字节到dest所指内存区域 |
char *strcpy(char *dest,char *src) | 把src所指由NULL结束的字符串复制到dest所指的数组中 |
char *strncpy(char *dest,char *src) | 把src所指由NULL结束的字符串复制到dest所指的数组中 |
char *strcat(char *dest,char *src) | 把src所指的’0’添加到dest结尾处(覆盖dest尾处的’\0’) |
char * strchr(char *s,char c) | 查找字符串s中首次出现字符c的位置 |
int strcmp(char *s1,char *s2) | 比较字符串s1和s2 |
int stricmp(char *s1,char *s2) | 比较字符串s1和s2,但不区分字母的大小写 |
int strcspn(char *s1,char *s2) | 在字符串s1中搜寻s2中所出现的字符 |
char * strdup(char s) | 复制字符串s |
int strlen(char *s) | 计算字符串s的长度 |
char *strlwr(char *s) | 将字符串s转换为小写形式 |
char *strupr(char *s) | 将字符串s转换为大写形式 |
char *strmat(char *dest,char *src,int n) | 把src所指字符串的前n个字符添加到dest结尾处(需要dest足够大的‘\0’,并添加‘0’) |
int strncmp(char *s1,char *s2 ,int n) | 比较字符串s1和s2的前n个字符 |
int strnicmp(char *s1,char *s2 , int n) | 比较字符串s1和s2的前n个字符但不区分大小写 |
char *strncpy(char *dest ,char *src,int n) | 把src所指由NULL结束的字符串的前n个字节复制到dest所指的数组中 |
char *strpbrk(char *s1,char *s2) | 在字符串s1中寻找字符串s2中任何一个字符相对应的第一个字符的位置,至字符串NULL不包括在内 |
char *strev(char *s) | 把字符串s的所有字符的顺序颠倒过来(不包括空字符串NULL) |
char *strset(char *s, char c) | 把字符串s中的所有字符都设置成字符c |
char *strstr(char *haystack,char *needle) | 从字符串haystack中寻找字符串needle第一次出现的位置(不比较结束符NULL) |
char * strtok(char *s, char delim) | 分解字符串为一组标记串。s为要分解的字符串,delim为分隔符字符串 |
int stnicmp(char *s1,char *s2 , int n) | 比较字符串s1和s2的前n个字符但不区分大小写 |
实现链表
// DoubleList.c
#include <stdio.h>
#include <stdlib.h>typedef int ElemType;
typedef struct _DoubleListNode
{ElemType data;struct _DoubleListNode *prior; // 前驱指针struct _DoubleListNode *next; // 后驱指针
}DoubleListNode;
typedef DoubleListNode* DoubleLinkList;DoubleLinkList ListInit()
{DoubleLinkList list = (DoubleLinkList)malloc(sizeof(DoubleListNode));list->prior = NULL;list->next = NULL;list->data = -1;return list;
}int ListInsert(DoubleLinkList list, int data, int n)// 将node插入到第n位,n从1开始
{if(list==NULL || n<1) // 判断参数有效性return -1;DoubleListNode* cur = list; // cur指向当前结点,初始化指向头结点int cur_i=0; // cur_i表示当前结点的序号,0-头结点while(cur && cur_i<(n-1))// 当前结点有效,且不是插入位置的前一个结点,就后移一个{cur = cur->next;cur_i++;}if(!cur) // 当前结点无效,说明已经移动到最后{printf("[%s %d]error din't have No.%d\n", __FUNCTION__,__LINE__, n);return -1; // 链表没有 n 那么长}DoubleListNode* new = (DoubleListNode*)malloc(sizeof(DoubleListNode));new->data = data;new->prior = cur;new->next = cur->next;if(cur->next) // 在最后一个结点插入时,cur->next==NULLcur->next->prior = new;cur->next = new;return 0;
}// 删除第n个结点,且将删除的值通过data传出
int ListDelete(DoubleLinkList list, int *data, int n)
{if(list==NULL || data==NULL || n<1)return -1;DoubleListNode* cur = list; // cur指向当前结点,初始化指向头结点int cur_i=0; // cur_i表示当前结点的序号,0-头结点while(cur->next && cur_i<(n-1)){// 下个结点有效,且当前位置不是删除位置的前一个,就后移一个cur = cur->next;cur_i++;}if(!cur->next) // 下个结点无效,说明已经移动到最后{printf("[%s %d]error din't have No.%d\n", __FUNCTION__,__LINE__, n);return -1; // 链表没有 n 那么长}DoubleListNode *delete = cur->next;delete->prior->next = delete->next;delete->next->prior = delete->prior;free(delete);return 0;
}int ListFind(DoubleLinkList list, int *data, int n)
{if(list==NULL || data==NULL || n<1)return -1;DoubleListNode* cur = list->next;// 指向第一个节点int cur_i=1; // i表示当前结点的序号while(cur && cur_i<n) // 当前结点有效,且当前位置不是查找位置n,就往后移动一个{cur = cur->next;cur_i++;}if(!cur) // 当前结点无效,说明已经移动到最后{printf("[%s %d]error din't have No.%d\n", __FUNCTION__,__LINE__, n);return -1; // 链表没有 n 那么长}*data = cur->data;printf("[%s %d]find No.%d = %d\n", __FUNCTION__,__LINE__, n,*data);return 0;
}void ListDestroy(DoubleLinkList list)
{DoubleListNode* cur = list->next; // 指向第一个节点DoubleListNode* next = NULL; // 用于保存下个结点地址while(cur) // 当前结点有效,就往后移动{next = cur->next; // 保存下个结点地址//printf("[%s %d]delete %d\n", __FUNCTION__,__LINE__, cur->data);free(cur); // 删除当前结点、并释放内存cur = next; // 将当前结点指针指向下个结点}list->prior = NULL;list->next = NULL;
}void ListPrintf(DoubleLinkList list)
{DoubleListNode* cur = list->next;// 指向第一个节点printf("list:[");while(cur){printf("%d,",cur->data);cur = cur->next;}printf("]\n");
}int main()
{DoubleLinkList list=ListInit();int data=0;printf("Linklist is empty !!! \n");ListInsert(list, 2, 2); // 空链表时,验证插入ListDelete(list, &data, 1); // 空链表时,验证删除ListFind(list, &data, 1); // 空链表时,验证查询ListDestroy(list); // 空链表时,验证销毁printf("\ninsert 3 data\n");// 正常插入3个数据ListInsert(list, 1, 1);ListInsert(list, 2, 2);ListInsert(list, 3, 3);ListPrintf(list);printf("\n验证错误值\n");ListInsert(list, 5, 5); // 验证插入ListDelete(list, &data, 4); // 验证删除ListFind(list, &data, 4); // 验证查询printf("\n正常操作\n");// 正常操作ListFind(list, &data, 2);printf("delete 2,now\n");ListDelete(list, &data, 2);ListPrintf(list);printf("Insert 4 to 2,now\n");ListInsert(list, 4, 2);ListPrintf(list);printf("Destroy ,now\n");ListDestroy(list);ListPrintf(list);return 0;
}