#include "stdio.h"
#include "stdlib.h"
#include "time.h"
int main(){
int s[10]={0};
int t;
srand(time(0));//use current time as seed for random generator
for (int i=0;i<10;i++) {
s[i]=rand()%100;
printf("%5d",s[i]);
}
putchar(10);
printf("rand_max:%d\n",RAND_MAX);
for(int i=0;i<10-1;i++){
for(int j=i+1;j<10;j++){
if(s[i]>s[j]){
t= s[i];
s[i]=s[j];
s[j]=t;
}
}
}
for (int i=0;i<10;i++) {
printf("%5d",s[i]);
}
printf("\n%d", 1 + rand()/((RAND_MAX + 1u)/100));
//1u表示无符号整型,系统默认有符号整型,unsigned
}
70 54 82 63 6 33 22 56 46 79
rand_max:2147483647
6 22 33 46 54 56 63 70 79 82
86
int main(){
char s[] = "12345678";
printf("%s\n",&s[1]);//第二个地址开始遍历,遍历到‘\0’结束
printf("%s\n",&s[0]);//作为第一个地址
printf("%s",s);//数组名作为数组的第一个地址,不用&取地址符
}
2345678
12345678
12345678
#include "string.h"
int main(){
char a[10], b[]="adsffadsfsaf" ;
strcpy(a,b);
}
//copy存放的空间不足直接报错,不截断
//Terminated due to signal: ILLEGAL INSTRUCTION (4)
#include "stdio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"
#define N 10
int main(){
int i,j;
int s[N][N]={0};//初始化一定要做好
// 初始化,第一列,对角线
for (i=0;i<N;i++){
s[i][0]=1;
s[i][i]=1;
}
// 中间内容,s[1][0]开始,数值为2,s[i][j]=s[i-1][j-1]+s[i-1][j];
for (i=2;i<N;i++) {
for (j=1;j<=i-1;j++) {
s[i][j]=s[i-1][j]+s[i-1][j-1];
}
}
// 输出 for for j=0;j
for(i=0;i<N;i++){
for (j=0;j<=i;j++){
printf("%5d",s[i][j]);
}
putchar(10);
}
}
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
#include
int main(int argc, char *argv[]) {
int fac (int a);
printf("%d ",fac(10));
}
int fac (int a){
int f;
if(a<0){
printf("阶乘不能小于0");
}else if(a==0||a==1){
f=1;
}else{
f=fac(a-1)*a;
}
return f;
}
3628800
#include "stdio.h"
void hanoi(int n,char one,char two,char three);
int main(){
hanoi(3, 'A', 'B', 'C');
}
void hanoi(int n,char one, char two,char three){
//从one移动到three需要借助two
void move (char x, char y);
if (n==1) {
move(one, three);
//当n=1时,代表只剩一个盘子需要移动,最后一个盘子从one移动到three不需要借助其他位置
}else {
hanoi(n-1, one, three, two);
//第一个操作,从第一个位置移动到第二个位置,借助three位置
move(one,three);
hanoi(n-1, two, one,three);
}
}
void move (char x,char y){
printf("%c -> %c \n",x,y);
}
//解体思路:
//一个盘子直接从A-C
//两个盘子要:A-B、A-C,B-C
//只要看懂两个盘子如何移动,结合一个盘子移动,就能写出顺序
#include
int main(int argc, char *argv[]) {
int a[][2]={1,2,3,5,6};
for (int i=0;i<3;i++) {
for (int j=0;j<2;j++) {
if (a[i][j]=='\0') {
continue;
}
printf("%d ",a[i][j]);
}
}
printf("\n %d ",a[0][4]);
printf("\n %d ",a[0][5]);
printf("\n %d ",a[0][6]);
}
Untitled 3.c:16:18: warning: array index 4 is past the end of the array (which contains 2 elements) [-Warray-bounds]
printf("\n %d ",a[0][4]);
^ ~
Untitled 3.c:4:2: note: array 'a' declared here
int a[][2]={1,2,3,5,6};
^
Untitled 3.c:17:18: warning: array index 5 is past the end of the array (which contains 2 elements) [-Warray-bounds]
printf("\n %d ",a[0][5]);
^ ~
Untitled 3.c:4:2: note: array 'a' declared here
int a[][2]={1,2,3,5,6};
^
2 warnings generated.
1 2 3 5 6
6
0
ns 2 elements) [-Warray-bounds]
printf("\n %d ",a[0][6]);
^ ~
Untitled 3.c:4:2: note: array 'a' declared here
int a[][2]={1,2,3,5,6};
^
3 warnings generated.
1 2 3 5 6
6
0
-1591672656
#include
int htoi(char s[]);
int main(int argc, char *argv[]) {
char array[1]="a";
printf("%c ",array[0]);
printf("%d",htoi(array));
}
int htoi(char s[]){
int i,n;
n=0;
for (i=0;s[i]!='\0';i++) {
if (s[i]>='0'&&s[i]<='9') {
n=n*16+s[i]-'0';
}
if (s[i]>='a'&&s[i]<='f') {
n=n*16+s[i]-'a'+10;
}
if (s[i]>='A'&&s[i]<='F') {
n=n*16+s[i]-'A'+10;
}
}
return n;
// a11
// ((0*16+'a'-'a'+10)*16+'1'-'0')*16+'1'-'0'
// 10*16+1*16+1
// 160*16+1
// =(10*16^2)+(1*16^1)+(1*16^0)
// =2560+16+1
// =2577
//
}
#include
void convert(int );
int main(int argc, char *argv[]) {
convert(10);
}
void convert(int n){
int i;
if((i=n/10)!=0){
convert(i);
}
putchar(n%10+'0');//字符转换+‘0’
putchar(32);
}
#include
int main(int argc, char *argv[]) {
int a=0;
double *b;
b=&a;
int * c;
c=&a;
printf("b pointer:%d\n",b);
printf("a pointer:%d\n",&a);
printf("c pointer:%d\n",c);
printf("sizeof a %d\n",sizeof(a));
printf("sizeof b %d\n",sizeof(b));
printf("%d\n",*b);
printf("%d",*c);
return 0;
//指向的地址相同,指针的内容不仅包裹纯地址还包括了,还包括了数据的类型,数据的存储方式和使用的内存空间可能不同,
//b=&a;进行了强制转换,将a为int型的地址转换为double型的地址赋值给b,但是因为基类型是不同的,地址相同得出的数据也是不同的,地址相同也只是指地址的起始位置相同,int占用的是4个字节存储数值,超出范围的内存是未知的,double的大小是8个字节,四个字节中长度未知,所以得出的数值是根据double的运算方法从8个字节的内存中计算得出的;
}
#include
void SwapPointer(int **,int **);
void Swap(int *a,int *b);
void SwapP(int *a,int *b);
int main(int argc, char *argv[]) {
int a=1,b=2;
int *a1=&a,*b1=&b;
printf("原值 a:%d b:%d\n",a,b);
printf("原值 a1:%d b1:%d\n",a1,b1);
printf("Swap:\n");
Swap(a1, b1);
//普通的 传引用 方式交换 a b值
//a1 的值是 变量a的地址 ,传递给函数的是a1的值,变量a的地址,交换了int 型指针变量a1 的指向,使其指向变量b,
printf(" a:%d b:%d\n",a,b);
printf(" a1:%d b1:%d\n",a1,b1);
//错误例子示范
SwapP(a1, b1);
//企图通过函数改变指针指向,没有考虑好给函数的实参和SwapP的形参之间的关系是值传递的关系,Swap中的a和b只拿到了实参的值,就是a和b的地址或&a &b,也别想直接交换a和b的地址,变量从创建以来,地址就已经固定,不会改变
printf("SwapP:\n");
printf(" a:%d b:%d\n",a,b);
printf(" a1:%d b1:%d\n",a1,b1);
//============通过函数改变指针指向============
//根据上面,实参和形参的传递方式是值传递方式,只要改变值传递的方式就通过函数改变指针的指向
SwapPointer(&a1,&b1);
//传递 指针的地址 给 指针的指针
printf("SwapPointer:\n");
printf(" a:%d b:%d\n",a,b);
printf(" *a1:%d *b1:%d\n",*a1,*b1);
printf(" a1:%d b1:%d\n",a1,b1);
}
void SwapPointer(int **a,int **b){
int *temp;
temp = *a;
//传入的是指针变量的地址,及指针的指针,或指向指针的指针
//a的值是a1的地址,用temp来临时存放a1的地址
*a =*b;
*b = temp;
}
void Swap(int *a,int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void SwapP(int *a,int *b){
int *temp;
temp = a;
a = b;
b = a;
}
#include
int main(int argc, char *argv[]) {
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p;
for (p=a;p<a+10;p++) {
printf("%d ",*p);
}
putchar(10);
p=a;
for (int i=0;i<10;i++) {
printf("%d ",*(p+i));
}
//第一种的速度是比第二种的速度要快,使用 [] 变址运算符,会转换为*(a+i)的形式,经过一次计算得出元素地址,速度会比第一种慢
}
#include
int main(int argc, char *argv[]) {
int a[2][8]={11,20,3,4,5,6,7,8,9,10};
int *p;
int *b = *(a+0)+0;
p=a;
for (int i=0;i<2;i++) {
for (int j = 0;j<8;j++) {
if (j%8==0) {
printf("\n");
}
printf("(%d,%d) ",&a[i][j],a[i][j]);
}
}
putchar(10);
printf("%d p\n",p);
printf("%d a\n",a);
printf("%d *a\n",*a);
printf("%d a+1\n",a+1);
printf("%d *a+1\n",*a+1);
printf("%d *(a+1)+1\n",*(a+1)+1);
printf("%d *a+1\n",*a+1);//可以转为*(a+0)+1
printf("%d **a+1\n",**a+1);//&a[0]上的值+1,就是a[0][0]+1
printf("%d *a+1+1\n",*a+1+1);//先进行指针运算
printf("%d (*(a+0)+1)\n",(*(a+0)+1));
printf("%d *(*a)\n",*(*a));
printf("%d *a\n",*a);
printf("%d &*(a+0)\n",&*(a+0));
printf("%d sizeof(a[1][1])\n",sizeof(a[1][1]));
printf("%d sizeof(a[0])\n",sizeof(a[0]));
printf("%d sizeof(*a)\n",sizeof(*a+1));
printf("%d sizeof(*a)\n",sizeof(a));
//二维数组指针 基类型 问题
printf("%d sizeof(a)\n",sizeof(a));//指针a的基类型是 int型的二维数组
printf("%d sizeof(*a)\n",sizeof(*a));//指向的是二维数组的第一列,指向一维数组,可通成*(a+0)或a[0]
printf("%lu sizeof(*a)\n",sizeof(*(*(a+0)+0)));//指向的是二维数组的第一列,指向一维数组,可通成*(a+0)或a[0]
printf("%d (*(a+0)+0)\n",*(a+0)+0);
printf("%d (*(a+0)+0)\n",sizeof(*(a+0)+0));//指针变量大小为8
int *d;
printf("%d *d\n",sizeof(d));//指针变量大小为8,什么类型都为8
double *e;
printf("%d *e\n",sizeof(e));
}
// (-339044768,11) (-339044764,20) (-339044760,3) (-339044756,4) (-339044752,5) (-339044748,6) (-339044744,7) (-339044740,8)
// (-339044736,9) (-339044732,10) (-339044728,0) (-339044724,0) (-339044720,0) (-339044716,0) (-339044712,0) (-339044708,0)
// -339044768 p
// -339044768 a
// -339044768 *a
// -339044736 a+1
// -339044764 *a+1
// -339044732 *(a+1)+1
// -339044764 *a+1
// 12 **a+1
// -339044760 *a+1+1
// -339044764 (*(a+0)+1)
// 11 *(*a)
// -339044768 *a
// -339044768 &*(a+0)
// 4 sizeof(a[1][1])
// 32 sizeof(a[0])
// 8 sizeof(*a)
// 64 sizeof(*a)
// 64 sizeof(a)
// 32 sizeof(*a)
// 4 sizeof(*a)
// -339044768 (*(a+0)+0)
// 8 (*(a+0)+0)
// 8 *d
// 8 *e
void copy_string(char * from,char * to){
//方法1
while ((*to=*from)!=0) {
to++;
from++;
//省去了最后*to=‘\0‘的操作
}
//方法2
{
while ((*to++=*from++)!=0);
//先++,然后*,赋值,判断,循环
}
//方法3
//判断是否等于0可以直接作为循环判断条件,
{
while (*from) {
*to++=*from++;
}
*to='\0';
}
//方法4
//再简化
{
while (*to++=*from++);
//这句是真的好用,自己找到结尾
}
}
#include
#include "string.h"
void SortString(char *string[],int N);
void PrintString(char *string[],int N);
int main(int argc, char *argv[]) {
char *string[4]={"B","A","C","D"};
// SortString(string, 4);
// PrintString(string, 4);
char **p=string;
printf("string :%d\n",string);
printf("*string :%s\n",*string);
//string 的值就是“B”字符串常量的地址
printf("p: %d\n",p);
//输出的是p的值,p的值存放的是string中存放的值,及“B”字符串常量的地址
printf("*p: %s\n",*p);
//p和string是同级关系,存储的值相同,但是是两个不同的指针,指向同一个地址
}
void SortString(char *string[],int N){
int k;
for (int i=0;i<N-1;i++) {
k=i;
for (int j=i+1;j<N;j++) {
if (strcmp(string[k], string[j]) > 0) {
k=j;
}
}
if(k!=i){
char * temp=string[k];
string[k]=string[i];
string[i]=temp;
//改变指针指向
}
}
}
void PrintString(char *string[],int N){
for (int i=0;i<N;i++) {
printf("%s\n",string[i]);
//直接按原顺序输出就行
}
}
string :-523356560
*string :B
p: -523356560
*p: B
看网上对Windows的可执行文件输入main函数参数还是比较多的,找挺久也难找到mac给main函数输入参数的,所以这里补充一下,mac基础源于Unix,用Unix的方法应该是通用的
#include
int main(int argc, char *argv[]) {
printf("argc: %d",argc);
putchar(10);
for (int i=0;i<argc;i++) {
printf("%s\n",*(argv+i));
}
}
一个简单的把main函数参数打印
主要看mac如何给入参数
使用的软件是CodeRunner,可以使用Run Settings直接给参数
注意这个命名中间有括号,建议不要这样命名,进入所在文件夹,如果有空格,指定时要加 \ 转义符
后面直接跟argv的参数就行,空格间隔
#include
#define N 10
void min_max_swap(int *array);
int main(int argc, char *argv[]) {
int array[N]={97,1,2,3,4,5,6,7,8,9};
printf("%d \n",*(array+N-1));
int *p=array;
printf("%d\n",p);
printf("%d\n",*p++);
//使用++前的值
printf("%d\n",p);
int *p2 = array;
printf("%d\n",p2);
printf("%d\n",*++p2);
//使用++后的值
printf("%d\n",p2);
min_max_swap(array);
for (int *p = array;p<array+N;p++) {
printf("%4d,",*p);
}
printf("\b");
}
void min_max_swap(int *array){
int *min,*max,temp;
min=max=array;
for (int *p=array+1;p<array+N;p++) {
if(*p > *max){
max = p;
}else if(*p < *min){
min = p;
}
}
temp = *array;
*array = *min;
*min = temp;
if (max == array) {
max = min;
}
temp = *(array+N-1);
//注意最后一个位置是9,不是10,容易越界
//注意优先级问题
//*优先级高于+
//但++的优先级又高于*
*(array+N-1)=*max;
*max = temp;
//先都指向首地址
}
#include
int main(int argc, char *argv[]) {
char str[20];
scanf("%s",str);
//字符指针指向没设定长度的字符串常量,不能进行修改,scanf不能输入
char * p = str;
int i=0;
while (i++,*p++);
//逗号运算符
printf("%d",i-1);
//while结束时,结果会多一次,注意
}
学习辅导
指向 int*型指针 和 指向 char*型指针 的使用区别
int 例题需要操作地址上的值
char 需要操作地址,主要获取地址进行操作
#include
int main(int argc, char *argv[]) {
struct Lwh{
int i;
char j;
float a;
double b;
}lwh1 ={.i =10,.b = 2};//这种方式对单独成员初始化
struct Lwh lwh2 = {.b=3},lwh3; //这种写法,不能先定义再初始化
// lwh3 = {.j='a'};//不能分开写
printf("%d\n",lwh3.j);
printf("%d\n",lwh1.i);
printf("%d\n",lwh1.j);
printf("%f\n",lwh1.a);
printf("%f\n",lwh1.b);
printf("%f lwh2 \n",lwh2.b);
// 10
// 0
// 73896
// 2.000000
// 3.000000 lwh2
//char型默认初始化为'\0',指针初始化为NULL,数值型初始化为0
}
#include
int main(int argc, char *argv[]) {
struct Lwh{
int i;
char j;
float a;
double b;
}lwh1 ={10,'a',12,13};//这种方式对单独成员初始化
printf("%lu &lwh1\n",&lwh1);
printf("%lu i\n",&lwh1.i);
printf("%lu j\n",&lwh1.j);
printf("%lu a\n",&lwh1.a);
printf("%lu b\n",&lwh1.b);
printf("%lu &lwh+1\n",&lwh1+1);//+1的基类型是以结构体为单位,这样的方法应该结合结构体数组,和结构体指针,位置停留在结构体的末尾
//根据内存显示,结构体占用情况分别是4、4、8、8,此结构体占用总空间为24
printf("%lu \n",sizeof(lwh1));
printf("%lu \n",sizeof(double));
printf("%lu \n",sizeof(float));
//占用的空间并不和原类型大小完全一致
}
#include
int main(int argc, char *argv[]) {
struct Lwh{
int i;
char j;
float a;
double b;
}lwh1 [3]={{11,'a',21,31},{12,'b',22,32},{13,'c',23,33}};
struct Lwh *lwhp = lwh1;
printf("%d (*lwhp).i\n",(*lwhp).i);
printf("%d lwhp->i\n",lwhp->i);
printf("%d (*(lwhp+1)).i\n",(*(lwhp+1)).i);
//理清关系
//(lwhp+1)在内存层面上,根据结构体分配的内存大小,加上一个结构体的内存大小,将位置从第一个结构体到头部移动到第一个结构体到尾部,正是第二个结构体头部
//(*(lwhp+1))成员运算符‘.’比 *取值符 优先级高,当前层面是内存层面,需要进行一次取值操作,取出结构体值,
//最后才是找到结构体中成员的部分.i
printf("%d (lwhp+1)->i\n",(lwhp+1)->i);
//内存层面+1,然后直接指向成员i
}
#include
#include
#define SIZE sizeof(struct Link)
struct Link{
int num;
float score;
struct Link * next ;
};
struct Link * create(void);
int main(int argc, char *argv[]) {
struct Link *pt;
pt = create();
while (pt->next) {
printf("%d %f print\n",pt->num,pt->score);
pt = pt->next;
//输出完指向下一个节点,直到==null
}
return 0;
}
//返回头节点
struct Link * create(void){
struct Link * head,*P1,*P2;
int n=0;
P1=P2=malloc(SIZE);//返回的是一个地址
head = NULL;
scanf("%d,%f",&P1->num,&P1->score);
while (P1->num) {
n++;
//第一次head指向链表头
if(n==1){
head = P2;
}
P1 = malloc(SIZE);
//申请内存空间,赋值给P1空间
P2->next = P1;
//通过成员next存放下一个节点的地址,将两块内存进行连接
P2= P1;
//”重新定位“,此时P1的next还是null,进行下一个节点的连接就要像这个新节点定位,用这个新节点的next存放下一个新节点
//因为这是单向链表,所以上一个节点的位置已经不需要知道了,所以让P2指向P1,待下一个新节点申请再链接
scanf("%d,%f",&P1->num,&P1->score);
//P1赋值
}
P1->next = NULL;
return head;
}
#include
enum test{a=5,c,d,e,f=1,g=1,h,i,j,k}A;
//单独指定值后,后面未指定的值+1,不指定值默认从零开始加,相同的值也是有的
int main(int argc, char *argv[]) {
A =a ;
printf("%d\n",A);
printf("%d\n",c);
printf("%d\n",d);
printf("%d\n",e);
printf("%d\n",f);
printf("%d g\n",g);
printf("%d\n",h);
printf("%d\n",i);
printf("%d\n",j);
printf("%d\n",k);
}
5
6
7
8
1
1 g
2
3
4
5
问题出自:2017年韩山师范学院本科插班生考试 第3题
int myabs(int n)
{
return n * ((n>>31<<1) +1);
}
整型变量 n 右移31位 左移1位 +1 乘 n
//以-2为 n 举例
//n * ((n>>31<<1)+1)
//-2*(-2>>31<<1)+1
1000000000 0000000000 0000000000 10
//-2的原码
1111111111 1111111111 1111111111 01
//-2的反码
1111111111 1111111111 1111111111 10
//-2的补码 -2反码+1
//这是-2 在计算机中的表示 以源码的补码表示
1111111111 1111111111 1111111111 11
//-2 >> 31
1111111111 1111111111 1111111111 10
//<< 1
1111111111 1111111111 1111111111 11
//+1
//这是-1在计算机中的表现形式
//补码转源码:符号位不变,减1取反
1000000000 0000000000 0000000000 01
//-1 原码
//-2 * -1 = 2 最后得出n的绝对值为2
//正数就不举例了
#include
#include "stdlib.h"
#include "string.h"
int main(int argc, char *argv[]) {
char a[]={"abc"};
char b[]="abc";
char c[]={'a','b','c','\0'};
char d[]={'a','b','c','\0'};
char *e = (char *)malloc(sizeof(char)*4);
//其他属于局部变量,退出所在函数会被释放,这种方式需要手动释放free
strcpy(e,"abc");
char g[]={'a','b','c'};
// printf("%s",g);abc‡X¿õ⁄没有找到结尾乱码
printf("%d",strlen(c));
printf("%d",strlen(g));//长度为9
//不计算\0;
//被认为是一个3字节的字符数组,所以没有预留\0的空间,对很多字符串的操作将出错
// char *f ="abc"; 这种定义的字符串是常量
}
#include
#include "stdlib.h"
#include "string.h"
int ** malloc2d(int r,int c);
int main(int argc, char *argv[]) {
int ** t;
t = malloc2d(2, 3);
//多种赋值方式
*(*(t+0)+1)=1;
*(*(t+1)+2)=2;
t[1][1]=3;
for (int i=0;i<2;i++) {
//单循环或双循环
for (int j = 0 ;j<3;j++) {
printf("%d ",*(*(t+i)+j));
}
putchar(10);
}
free(t);
}
//row 行
//column 列
//主要是这两条申请语句
int ** malloc2d(int r,int c){
int ** t= (int ** )malloc(r*sizeof(int*));
for (int i=0;i<r;i++) {
t[i] = (int *)malloc(c*sizeof(int));
//初始化,不初始化默认的数值也默认0
for (int j=0;j<c;j++) {
*(*(t+i)+j) = 0;
}
}
//从零列开始
return t;
}
0 1 0
0 3 2
int factorial (int n){
if(n==0)return 1;
return n*factorial(n-1);
}
//递归式
int fibonacci(int n){
if(n<=1)return 1;
return fibonacci(n-1)+factorial(n-2);
}
//动态规划
//保存已经计算过子问题的解,避免重复计算
int Fibonacci(int n){
int *f =(int *)malloc(sizeof(int)*(n+1));
f[0]=f[1]=1;
for (int i=2;i<=n;i++) {
f[i]=f[i-1]+f[i-2];
}
free(f);
return f[n];
}
//动态规划
//只使用了两个位置,十分精妙,单数时,存放在1位,双数时存放在0位,反复叠加,最后在单数停下所有的叠加
int fibonacci2(int n){
int f[2] ;
f[0]=f[1]=1;
while (--n) {
f[n&1]=f[0]+f[1];
}
return f[1];
}
printf("%d\n",3&1);
//0011
//0001
//1
//f[1] = f[0]+f[1]
//f[1] = 2
printf("%d\n",2&1);
//0010
//0
//f[0] = f[0]+f[1]
//f[0] = 3
printf("%d\n",1&1);
//0001
//1
//f[1] = f[0]+f[1]
//f[1] = 5
/***********判断是不是素数************/
int prime(int n)
{
int i;
for(i=2;i<=sqrt(n);i++)//这里就涉及到使用根号的素数判断
{
if(n%i==0)
{
return 0;//不是素数返回0
}
}
return 1;//是素数返回1
}
void print(int n)
{
int i;
for(i=2;i<=n/2;i++)
{
if(prime(i)&&prime(n-i))//判断拆分出的两个数是不也是素数
{
printf("%d=%d+%d\n",n,i,n-i);
}
}
}
int find(int n){
int b,e,sum,cnt;
b = e = sum = 1;
cnt =0;
while (b<=n/2) {
if(sum<n){
e++;
sum+=e;
}else if(sum >n){
sum-=b;
b++;
}else if(sum == n){
sum -=b;
b++;
cnt ++;
}
}
return cnt;
}
int gcd (int a,int b){
if(b==0)return a;
return gcd(b,a%b);
}
//三个数求最小公约数就再加一层
算法
程序
理解问题
算法复杂性
所设计的算法产生的程序,所耗费的资源,保证正确性
计算机资源:时间,空间
n是问题的规模
I为n,n为规模,在n规模时,算法使用的时间最大,为最坏
渐进概念
认识符号概念
n是问题规模,f(n)和g(n)都是复杂性的函数
O
欧米伽 下界,计算时间下界由欧米伽
塞塔 既是上界也是下界
f(n)=O(n2)这样的表达并不严谨O(n2)是函数集合的复杂性,应该写成f(n)属于 O(n^2),上面那种也能说,只是一种约定俗成,讲的是f(n)的阶, 是渐进的阶
帮助理解函数渐进阶
传递性
算数运算
O(max{f(n),g(n)})
f(n)和g(n)两条曲线,的每个数值点相加就是他的算数运算,这是一个他的渐进性,O的渐进形态,在fn和gn中取一个大的,不是两个函数相加,而是max取一个大的,渐进形态就是取一个大的,如果函数比较复杂,是有拐点的,一段是第一个函数一段是另一个函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cHXhTQC1-1621860154877)(…/…/…/Library/Application Support/typora-user-images/image-20210222021049425.png)]
算法中常用的函数
单调函数
取整函数不大于x的最大函数,天花板函数
复杂性排序
非递归实现就使用栈
层序遍历使用对队列,顺序为中左右、
测算树高度,左右子树分别递归叠加hl和hr,选出最大的h,+1,+1为根
树上157页通过位置的0和1来表示元素是否在集合中存在,提供了两种思想,一种是直接n长度的数组来实现,元素对应下标,数组通过设置0或1的方式来表达原子在数组中存在,这种方法比较消耗内存,n就是元素有效范围,当n十分大时,数组的大小也为n,十分容易造成空间的浪费,在并交差等操作时间复杂度都为O(n)复杂度
书上介绍的方法是,选用unsigned short 类型在作为数组存储单元的类型,这种类型占用2个字节,即16位Bit,当bit位的1位到16位可以表示0-----15
S->v[0],这一个数组单元就能表达0-----15,共16位的数,S->v[1]能表示16—31,
主要思想就是x存储在哪一个区间,和计算出1的左移次数,存放在当前这个区间的第几位
存储在哪一个区间
存储在区间中的第几个位置
BitMask 1<<(x&15) //相当于对x取余 %16
#include
#include "stdlib.h"
typedef struct bitset *Set;
typedef struct bitset {
int setsize;
int arraysize;
unsigned short *v;
}Bitset;
Set SetInit(int size){
Set S = (Set)malloc(sizeof(Set));
S->setsize =size;
S->arraysize = (size+15)>>4;
S->v = (unsigned short *)malloc(size*sizeof(unsigned short));
for (int i=0;iv[i]=0;
}
return S;
}
int ArrayIndex(int x){
// return x>>4;
return x/16;
//十六个单位为一个区间
}
unsigned short BitMask(int x){
// return 1<<(x&15);
x %=16;
return 1<=S->setsize)return ;
unsigned short a;
int i,p;
a = BitMask(x);
i = ArrayIndex(x);
p = S->v[i] |= a;
}
void SetDelete(int x,Set S){
// if(x<0 || x>=S->setsize)return ;
S->v[ArrayIndex(x)] &= ~BitMask(x);
}
int SetMember(int x,Set S){
return S->v[ArrayIndex(x)]&BitMask(x);
}
int main(int argc, char *argv[]) {
// printf("%d\n",sizeof(unsigned short));
//16位
Set S = SetInit(10);
SetInsert(16, S);
// SetInsert(36, S);
// SetInsert(13, S);
// SetInsert(0, S);
// SetInsert(5, S);
//0为第一区间的第一位
// SetInsert(16, S);
//16为第二区间的第一位
//每一个区间都能存放16位
// SetInsert(144, S);
// SetInsert(164, S);
// SetInsert(175, S);
printf("member :%d \n",SetMember(1,S));
SetInsert(3, S);//8
// SetInsert(2, S);//4
// SetInsert(2, S);//4
//12
// SetInsert(1, S);//2
// SetInsert(0, S);//1
// SetInsert(-1, S);//0
// SetInsert(-2, S);//0
// SetDelete(9, S);
// SetDelete(4, S);
for (int i=0;i<10;i++) {
printf("%hu ",S->v[i]);
}
printf("\n%d",1<<30);
}
和数因子,和数因子是从素数中产生的,最小的素数为2,m作为合数因子,从2开始,配合k+=m,删除合数因子的倍数,当m不断扩大时,如当m为5的时候,上一层的循环为4的时候,4已经被m为 2 的时候删除了,所以m走完素数2走素数3,跳过已经被删除的4直接走到5
每个元素有优先级
优先级可能重复
优先级高低由自己定义,数值大或数值小的作为高优先级
DeleteMin删除优先级最小的元素,主要关心优先级最小的元素
用树和字典实现优先队列都不是最高的,优先队列最关注的操作就是找优先级最高的元素
最小和最大堆,或称极小或极大优先级树,根节点小于左右子树,根节点是所有元素中最小的
堆实现
满足优先级树又满足近似满二叉树
近似满二叉树能用顺序存储,父子关系通过下标实现,
插入操作
删除操作
用堆进行排序
和选择排序相近
只是全部元素插入删除就能得到有序效率为O(nlogn),但这只是全部元素删除的时间复杂度,还需要加上建堆的时间
k为当前节点,m为底部位置,
建立初始堆
从下向上调整
n/2开始,一个for循环就能n/2的位置从下向上构建完成堆,调整每一个节点所在的子树调整为一个堆,第二个for循环意义不明,
#include
int sift(int r[],int k,int m){
int i,j;
int x;
i = k;
x = r[i];
j=2*i;
while (j<=m) {
if((j<m)&&(r[j]>r[j+1]))j++;
if(x>r[j]){
r[i]=r[j];
i=j;
j*=2;
}else {
break;
}
}
r[i]=x;
}
void heapsort(int r[],int n){
int i;
int x;
for (i=n/2;i>=1;i--) {
sift(r, i, n);
}
// for (i = n;i>=2;i++) {
// x = r[1];
// r[1] = r[i];
// r[i]=x;
// sift(r, 1, i-1);
//
// }
}
int main(int argc, char *argv[]) {
int r[9]={0,49,38,65,97,76,13,27,50};
heapsort(r,9);
for (int i=1;i<9;i++) {
printf("%d ",r[i]);
}
}
//注意指针叠加
int main(int argc, char *argv[]) {
int a[]={2,4,6,8,10,12,14};
int *p;
p = a+4;
printf("%d\n",*p++);//10
printf("%d\n",(*p)++);//12
printf("%d\n",*p);//13
printf("%d,%d\n",p[-2],*(a+4));//8,10
}
//正负数reverse反转
int reverse(int n){
int sign=1,m;
if(n<0){
sign =-1;
}
n = (n>=0?n:-n);
m=n%10;
while (n>=10) {
n = n/10;
m = m*10+n%10;
}
return sign*m;
}
存储结构
二分查找
int Binary_Search(int* a, int size, int val)
{
int pos = -1;//pos返回查找到的值的位置
if (a == nullptr || size < 1)//数组合法性检查
{
return pos;
}
int left = 0;
int right = size - 1;
while (left <= right)//当左端元素位置不等于右边元素位置时反复查找
{
int mid = (left + right) / 2;
if (val < a[mid])//若所查找值小于中间值,在前半部分查找
{
right = mid - 1;
}
else if (val > a[mid])//若所查找值大于中间值在后半部分查找
{
left = mid + 1;
}
else
{
pos = mid;//若已找到则终止循环
break;
}
}
return pos;//返回查找到的值所在位置
}
范围从0------ size-1
先判断array [2],20,缩小再判断,25
二叉树非空域
单链表上溢
算法四个性质
循环队列优点
基数排序
#include
#include "stdlib.h"
#define RADIX 10
void RadisSort(int array[],int l,int r){
int pow=1,max=1;
//申请临时数组b
int * b = (int*)malloc(sizeof(int)*(r+1));
//找出max,max的位数决定需要进行几次的排序
//算法思路,先根据个位数排序,然后根据十位数排序,然后。。
//排序的次数根据max的位数决定
for (int i=l;i<r;i++) {
max<array[i]?max=array[i]:max;
}
//pow 初始为1,第二轮变成pow会变为10,RADIX决定的是进制,如果是10进制就是10,八进制就是8
while (max/pow) {
//重制count
//根据count的统计来,来确定根据当前排序位应该处于什么位置
int count[RADIX]={0};
int i;
//统计array元素的位数
for ( i=l;i<r;i++) {
int k;
k = array[i]/pow%RADIX;
count[k]++;
}
//计算前缀和
//位数有相同的时候,进行增加,到时将元素放回去的时候要--
for ( i=1;i<RADIX;i++) {
count[i]+=count[i-1];
}
//临时存放到b中
//count需要--,以防相同位数将位置叉开
for ( i=r-1;i>=l;i--) {
b[--count[array[i]/pow%RADIX]]=array[i];
}
//写会array中
for ( i=l;i<r;i++) {
array[i]=b[i];
}
//进制
pow *=RADIX;
}
free(b);
//释放b临时数组
}
void printArray(int array[],int l,int r){
printf("\n");
printf("\n");
for (int i=l;i<r;i++) {
printf("%4d",array[i]);
}
printf("\n");
printf("\n");
}
int main(int argc, char *argv[]) {
int array[] ={39,457,657,39,436,720,355};
int i=0;
int size = sizeof(array) /sizeof(int);
RadisSort(array, 0, size);
printArray(array, 0, size);
}
数据的逻辑关系,数据的逻辑结构划分为 4类
地址计算
算法五特性
算法复杂度
排序受挫经验
基数排序
快速排序
冒泡排序
选择排序
一般两种方式,min记录值交换,或记录min下标交换
void selectSort(int array[] ,int length){
int i,j;
for ( i=0;i<length;i++) {
int min =i;
for ( j=i;j<length;j++) {
if (array[min]>array[j]) {
min =j;
}
}
swap(array[i], array[min]);
}
}
void selectS(int array[] ,int length){
int i,j;
for ( i=0;i<length;i++) {
int min =array[i];
for ( j=i;j<length;j++) {
if (min>array[j]) {
min =array[j];
swap(array[i], array[j]);
}
}
}
}
插入排序
两种方式,分开交换,一次性交换
分开交换交换次数少
一次性交换交换次数多
两者比较次数不变
void insertSort(int *array ,int length){
int j;
for (int i=1;i<length;i++) {
int temp = array[i];
for ( j=i;temp<array[j-1]&&j>0;j--) {
array[j]=array[j-1];
}
array[j] = temp;
}
}
void Insert(int *array ,int length){
int j;
for (int i=1;i<length;i++) {
for (int j=i;j>0;j--) {
if (array[j]<array[j-1]) {
swap(array[j], array[j-1]);
}
}
}
}
归并排序
数组实现
指针实现
应用举例
stackSplit 分两个栈,上下部分
combine 合并,顺序不变
括号匹配
计算后缀表达式
两个栈共享一个数组
多个栈使用游标实现记录栈顶栈底,可分配可分配空
findmin栈O1时间找到栈中最小元素
单词反转reverse
找亲兄弟,最右边大于自身的为请兄弟,给出每个元素请兄弟下标,没有亲兄弟为-1
初始化输出数组全为-1
push(0)
for(1-----n){
while(stackempty&&x[stacktop(s)]<=x[i])d[pop(s)]=i;
push(i,s);
}
冒泡排序 bubble
插入排序 insertion
选择排序 select
快速排序 quick
合并排序 merge
链表结构合并排序
计数排序 count
桶排序 bucket
基数排序 radix
应用举例
最大增序列问题
二维数组每行选择一个数组成一个递增序列
使用贪心策略,线从最后一行开始选一个最大的,最后一行的最大数决定了递增序列的最大数,自底向上,每行的最大值都要小于上一行的最大值
排序只有 0 1 2的数组
数值范围限制时用桶排序或基数排序
众数
最优服务次序,让服务平均等待时间最小
删除链表min到max区间的值
给定入栈序列,给出所有的出栈序列
回文
是否是合法序列
可以用两个变量分别记录入栈和出栈,循环范围为输入数组长度,如果是 I就i++如果是O就 j++,O操作只要i
带头节点的循环链表表示队列,设置一个指针指向队尾元素站点,设置队空,判队空,入队,出队
和书本中的初始化一样,分配一个表头节点不使用
从rear->指向的是表头节点,不存储东西的,结构是和书中的一样rear的位置是表尾巴,rear->next->next 是表头
#include
#include "stdlib.h"
typedef struct queuenode{
int data;
struct queuenode * next;
}QueueNode;
typedef struct {
QueueNode * rear;
}linkQueue;
void insertNode(linkQueue *Q,int x){
QueueNode * p = malloc(sizeof(QueueNode));
p->data = x;
p ->next = Q ->rear ->next;
Q->rear ->next = p;
Q ->rear = p;
}
int emptyQueue(linkQueue *Q){
return Q->rear ->next->next == Q->rear->next;
}
linkQueue * initQueue(void){
linkQueue * L = malloc(sizeof(linkQueue));
QueueNode * node = malloc(sizeof(QueueNode));
//注意malloc一个node然后再让link的指向
L->rear = node;
L->rear->next = L->rear;//指向自己
return L;
}
void printqueue(linkQueue * Q){
QueueNode *p;
p = Q->rear ->next->next;
//从节点开始遍历,p=p->next 指向,那个表头节点空节点时,刚好遍历完最后一个标为节点,rear,所以应该在rear->next时候停下
while (p!=Q->rear->next) {
printf("%d ",p->data);
p=p->next;
}
}
int deleteQueue(linkQueue *Q){
QueueNode *p;
p = Q ->rear ->next->next;
//先判空,然后从表头删除,指向表头节点的位置
if(emptyQueue(Q)){
printf("link NULL");
return -1;
}
int x = p->data;
if(p == Q->rear){
//最后一个节点
//要移动指针和rear的位置,使rear的位置停留在表头节点(空节点),指向也好指向自己
Q->rear = Q ->rear->next;
Q->rear->next = Q->rear;
}else {
Q ->rear ->next->next = p->next;
//改变指向,确定了新的头节点
}
free(p);
return x;
}
int main(int argc, char *argv[]) {
linkQueue * Q;
Q = initQueue();
insertNode(Q, 1);
insertNode(Q, 2);
insertNode(Q, 3);
deleteQueue(Q);
printqueue(Q);
}
使用tag 为0和tag为1表示front和rear相等时为空还是满
队首删除,队尾插入
初始front=rear=tag=0
isEmpty return (front==rear && tag == 0);
//为空返回1
isFull return (front==rear && tag == 1);
//full ret 1
EnQueue
if(!isFull){
//不满的前提下能插入
rear = (rear+1)%length;
if(rear == front) tag = 1;
}else{
exit(0);
}
DeQueue //同理,但是要返回front的值
getFront
if(!isEmpty){
return array[ (front+1)%10 ];
}else{
print。。
}
循环数组实现队列,要求从 rear删除,从front插入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ojUKBDVv-1621860154961)(…/…/…/Library/Application Support/typora-user-images/image-20210318235106302.png)]
解题关键在于初始化
这样是理解错误的,rear向右++,front向左–,方向应该一致,像正常的从尾巴插入,从头删除,是rear++,front++
改成从尾删除,从头插入,就要是rear–,front–,这里用到了–从头转到尾巴的方法就是(front-1+M)%M 能使指针指向尾部
#include
#include "stdlib.h"
#define M 5
typedef struct queue{
int array[M];
int front;
int rear;
}Queue;
void InQueue(Queue * Q,int x){
if(Q->rear == (Q->front-1+M)%M){
printf("full ");
}else {
Q->array[Q->front] = x;
Q->front = (Q->front-1+M)%M;
}
}
int DeQueue(Queue *Q){
//rear 删除 向左
if(Q->front == Q->rear){
printf("Empty");
return -1;
}else {
Q->rear = (Q->rear-1+M)%M;
return Q->array[(Q->rear+1+M)%M];
}
}
int main(int argc, char *argv[]) {
Queue * Q ;
Q = malloc(sizeof(Queue));
Q->front =0;
Q->rear = 0;
InQueue(Q, 1);
InQueue(Q, 2);
InQueue(Q, 3);
printf("%3d",DeQueue(Q));
printf("%3d",DeQueue(Q));
printf("%3d",DeQueue(Q));
printf("%3d",DeQueue(Q));
}
front 和rear的位置唯一的要求就是要一致
要注意的地方,rear删除要不然提前将这个位置的数据记录好,再移动,后续好返回记录好的数据,跟普通的链表同理,front指向的是表头的前一个位置,rear要删除也是在前一个位置,移动了就要将上一个位置返回,而不是移动后的位置
单链表实现选择排序
char* Strcat(char* str1, const char* str2) {
int n = strlen(str1);
int i = 0;
while (str1++[i + n] = str2++[i]);
return str1;
}
char* Strcat(char* str1,char* str2) {
char * p1= str1,*p2 = str2;
int len1 = 0,len2 = 0;
if(str1==NULL){
return str2;
}
if(str2 ==NULL){
return str1;
}
while (*p1++!='\0') {
len1++;
}
while (*p2++!='\0') {
len2++;
}
char * str3 = malloc(sizeof(char)*(len1+len2));
int i=0;
for (p1 = str1;*p1!='\0';p1++) {
*(str3+i) = *p1;
i++;
}
for (p2 = str2;*p2!='\0';p2++) {
*(str3+i) = *p2;
i++;
}
*(str3+i) ='\0';
return str3;
}
sqrt 筛选法
void daffodilNum(){
int x,y,z;
for (int i = 100;i<1000;i++) {
x = i/100;
y = i/10%10;
z = i%10;
if(i == x*x*x + y*y*y + z*z*z){
printf("%4d",i);
}
}
}
#define swap(A,B) int temp=A;A =B;B=temp;
void selectSort1(int array[],int length){
for (int i=0;i<length;i++) {
int min =i;
for (int j = i;j<length;j++) {
if(array[min]>array[j]){
min = j;
}
}
swap(array[min], array[i]);
}
}
void InsertSort2(int array[],int length){
int j ;
for (int i = 1;i<length;i++) {
int k = array[i];
for (j = i;j>0 && k<array[j-1] ;j--) {
array [j] = array[j-1];
}
array [j] = k;
}
}
void bubbleSort(int array[],int length){
for (int i=1;i<length;i++) {
for (int j=i;j>0;j--) {
if(array[j]<array[j-1]){
swap(array[j], array[j-1]);
}
}
}
}
void shellSort(int array[],int lenght){
for (int shell = lenght/2;shell>0;shell/=2) {
for (int i = shell;i<lenght;i++) {
if (array[i-shell]>array[i]) {
swap(array[i-shell],array[i]);
}
}
}
}
void mergeab(int array[],int left,int right){
int i = left;
int mid = (left+right)/2;
int j = mid +1;
int k=left;
while ((i<=mid)&&(j<=right)) {
if(array[i]<array[j]){
b[k++] = array[i++];
}else {
b[k++] = array[j++];
}
}
if(i>mid){
for (i=j;i<=right;i++) {
b[k++] = array[i];
}
//j 段未完成
}else {
for (;i<=mid;i++) {
b[k++] = array[i];
}
// i 段未完成
}
}
void copy(int a[],int b[],int left,int right){
for (int i =left;i<=right;i++) {
a [i] = b[i];
}
}
void mergeSort(int array[],int left,int right){
int m = (left +right)/2;
if(right<= left){
return;
}
mergeSort(array,left,m);
mergeSort(array,m+1,right);
mergeab(array, left, right);
copy(array,b,left,right);
}
//partition
int partition(int array[],int left,int rigth){
int i=left ,j = rigth+1;
int standarn = array[left];
while (1) {
while (standarn>array[++i]) {
if(i==rigth){
break;
}
}
while (standarn<array[--j]) {
}
if(i>=j){
break;
}
swap(array[i], array[j]);
}
swap(array[j], array[left]);
return j;
}
int randomi (int minIndex,int maxIndex){
return minIndex+(maxIndex-minIndex)*(1.0*rand()/RAND_MAX);
}
int randomPartition(int array[],int minIndex,int maxIndex){
int i = randomi(minIndex,maxIndex);
swap(array[i], array[i]);
return partition(array, minIndex, maxIndex);
}
//quicksort
void quickSort(int array[],int minIndex,int maxIndex){
if(minIndex>maxIndex)return;
int standarn = randomPartition(array, minIndex, maxIndex);
quickSort(array, minIndex, standarn-1);
quickSort(array, standarn+1, maxIndex);
}
#define radix 10
void RadixSort(int array[],int length){
int pow=1,max =-1;
int * temp_array=(int *) malloc(sizeof(int )*length);
for (int i=0;i<length;i++) {
if(max< array[i]){
max= array[i];
}
}
while (max/pow) {
int count[radix]={0};
for (int i=0;i<length;i++) {
++count [array[i]/pow%radix];
}
for (int i=1;i<radix;i++) {
count[i] += count[i-1];
}
for (int i=length-1;i>=0;i--) {
temp_array[--count[array[i]/pow%radix]] = array[i];
}
for (int i=0;i<length;i++) {
array [i]= temp_array[i];
}
pow *=radix;
}
free(temp_array);
}
void intarrayReverse(int array[],int length){
for (int i=0;i<length/2;i++) {
int temp = array[i];
array[i] = array[length-1-i];
array[length-1-i] = temp;
}
}
//正负数reverse反转
int reverse(int n){
int sign=1,m;
if(n<0){
sign =-1;
}
n = (n>=0?n:-n);
m=n%10;
while (n>=10) {
n = n/10;
m = m*10+n%10;
}
return sign*m;
}
void TreeReverse(Tree * p){
Tree * temp;
if(p){
temp = p->left;
p->left = p->rigth;
p ->rigth = temp;
TreeReverse(p->left);
TreeReverse(p->rigth);
}
}
Tree * findNode(Tree * p ,int x){
Tree *temp = p;
if(p){
if(p->left!=NULL || p->rigth!=NULL){
if(p->left->x == x){
if(p->rigth){
p = p->rigth;
printf("\n find succee %d",p->x);
return p;
}
}
if(p->rigth->x == x){
if(p->left){
p = p->left;
printf("\n find succee %d",p->x);
return p;
}
}
}
temp = findNode(p->left,x);
if(temp){
return temp;
}
temp = findNode(p->rigth,x);
return temp;
}else {
return NULL;
}
}
Tree * finderNode(Tree * p,int data){
Tree * temp = p;
if(p){
if(p->x ==data){
return p;
}
temp = finderNode(p->left,data);
if(temp){
return temp;
}
temp = finderNode(p ->rigth,data);
return temp;
}else {
return NULL;
}
}
Tree * findSearch(Tree* p ,int data){
while (p) {
if(p->x >data){
p = p->left;
}else if(p -> x <data){
p= p->rigth;
}else {
break ;
}
}
return p;
}
void binaryTreeInsertNode(Tree * head,int data){
Tree * node = newNode(data);
Tree * p =head;
Tree * partent =p;
while (p) {
partent = p;
if(p->x < data){
p = p->rigth;
}else if(p->x >data){
p = p->left;
}else {
return;
//不许插入相同元素节点
}
}
if(head == NULL){
//空树
partent = node;
}else {
if(partent->x < data){
partent->rigth = node;
}else {
partent->left = node;
}
}
}
int TreeMaxNode(Tree * p ,int data){
int max =data;
if(p){
if(max<p->x){
max = p->x;
}
max = TreeMaxNode(p->left,max);
max = TreeMaxNode(p->rigth,max);
return max;
}else {
return max;
}
}
int binarySearch(int array[],int left ,int right,int data){
int i = left;
int j = right;
while (i <= j) {
int mid = (i + j)/2;
if(data == array[mid])return mid;
else {
if(data <array[mid]) {
j =mid-1;
}else {
i = mid+1;
}
}
}
return -1;
}
Link* linkReverse(Link * L){
Link * left = NULL ,*mid = L->next ,*right = NULL;
while (right) {
right = mid->next;
mid ->next = left ;
left = mid;
mid = right;
}
right = newNode(0);
right ->next =mid;
return right;
}
//有表头节点的逆序
Link ListReverse(List & L){
link last = 0 ,cur= L->first , next;
while (cur) {
next = cur ->next ;
cur ->next = last;
last = cur;
cur = next;
}
L->first = last;
}
//书中不带表头节点链表
#include "stdio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"
#define N 10
int main(){
int i,j;
int s[N][N]={0};//初始化一定要做好
// 初始化,第一列,对角线
for (i=0;i<N;i++){
s[i][0]=1;
s[i][i]=1;
}
// 中间内容,s[1][0]开始,数值为2,s[i][j]=s[i-1][j-1]+s[i-1][j];
for (i=2;i<N;i++) {
for (j=1;j<=i-1;j++) {
s[i][j]=s[i-1][j]+s[i-1][j-1];
}
}
// 输出 for for j=0;j
for(i=0;i<N;i++){
for (j=0;j<=i;j++){
printf("%5d",s[i][j]);
}
putchar(10);
}
}
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
//递归式
int fibonacci(int n){
if(n<=1)return 1;
return fibonacci(n-1)+factorial(n-2);
}
//动态规划
//保存已经计算过子问题的解,避免重复计算
int Fibonacci(int n){
int *f =(int *)malloc(sizeof(int)*(n+1));
f[0]=f[1]=1;
for (int i=2;i<=n;i++) {
f[i]=f[i-1]+f[i-2];
}
free(f);
return f[n];
}
//动态规划
//只使用了两个位置,十分精妙,单数时,存放在1位,双数时存放在0位,反复叠加,最后在单数停下所有的叠加
int fibonacci2(int n){
int f[2] ;
f[0]=f[1]=1;
while (--n) {
f[n&1]=f[0]+f[1];
}
return f[1];
}
##森林转二叉树