寒假第一周学习笔记

求逆序数

在这里插入图片描述

归并排序

#include<stdio.h>//归并排序
#include<stdlib.h>
#define n 10
mergesort(int *a,int left,int right,int *temp)
{
    if(left>=right)return ;//递归结束条件,当只有一个时没必要排序
    int mid=(left+right)/2;
    mergesort(a,left,mid,temp);//对左边区域排序
    mergesort(a,mid+1,right,temp);//对右边区域排序
    int begin1=left,end1=mid;//标记左边第一元素和最后一个元素
    int begin2=mid+1,end2=right;//同理
    int i=left;//便于辅助函数拷贝
    while(begin1<=end1&&begin2<=end2)//左右两边相比,取小的那个拷贝到temp函数
    {
        if(a[begin1]>=a[begin2])
        {
            temp[i]=a[begin2++];
        }
        else
        {
            temp[i]=a[begin1++];
        }
        i++;
    }
    while(begin1<=end1)//考虑到左右两边标记未等于各自末标记点,将其拷贝,此时的是有序的数列,直接拷贝
    {
        temp[i++]=a[begin1++];
    }
    while(begin2<=end2)//同理
    {
        temp[i++]=a[begin2++];
    }
    for(i=left;i<=right;i++)//拷贝到原数组
    {
        a[i]=temp[i];
    }
}
int main()
{
    int *tem=(int *)malloc(sizeof(int )*n);//动态分配空间给辅助数组
    int a[n]={2,3,6,4,1,8,5,7,2,10};
    mergesort(a,0,9,tem);//调用归并排序函数进行排序
    free(tem);//释放内存
    for(int i=0;i<n;i++)
    {
        printf("%d ",a[i]);
    }
    return 0;
}

归并排序的时间复杂度为nlog(n),相对于快速排序是个不错的选择,主要利用分冶法和归并法,归并是分冶的倒叙,只不过归并时候进行了一一比较排序和,利用递归的方法进行排序,主要操作集中在归并上,利用到了辅助数组来存放临时排放好的数,最后拷贝到原数组。

本题目的求逆序数可以用归并排序求解,在归并排序的主体代码块中的相比较时插入sum+=(mid-begin1+1);即可求出逆序数有几个

在这里插入代码片#include<stdio.h>//归并排序
#include<stdlib.h>
#define n 5
int sum=0;
mergesort(int *a,int left,int right,int *temp)
{
    if(left>=right)return ;//递归结束条件,当只有一个时没必要排序
    int mid=(left+right)/2;
    mergesort(a,left,mid,temp);//对左边区域排序
    mergesort(a,mid+1,right,temp);//对右边区域排序
    int begin1=left,end1=mid;//标记左边第一元素和最后一个元素
    int begin2=mid+1,end2=right;//同理
    int i=left;//便于辅助函数拷贝
    while(begin1<=end1&&begin2<=end2)//左右两边相比,取小的那个拷贝到temp函数
    {
        if(a[begin1]>=a[begin2])
        {
            temp[i]=a[begin2++];
            sum+=(mid-begin1+1);
        }
        else
        {
            temp[i]=a[begin1++];
        }
        i++;
    }
    while(begin1<=end1)//考虑到左右两边标记未等于各自末标记点,将其拷贝,此时的是有序的数列,直接拷贝
    {
        temp[i++]=a[begin1++];
    }
    while(begin2<=end2)//同理
    {
        temp[i++]=a[begin2++];
    }
    for(i=left;i<=right;i++)//拷贝到原数组
    {
        a[i]=temp[i];
    }
}
int main()
{
    int *tem=(int *)malloc(sizeof(int )*n);//动态分配空间给辅助数组
    int a[n]={5,4,1,3,2};
    mergesort(a,0,4,tem);//调用归并排序函数进行排序
    free(tem);//释放内存
    for(int i=0;i<n;i++)
    {
        printf("%d ",a[i]);
    }
    printf("\n%d",sum);
    return 0;
}

在这里插入图片描述
由于数字长度远超计算机能表示数字最大范围,故而将竖式乘法拆分,例如·
在这里插入图片描述

在这里插入代码片char* multiply(char* num1, char* num2) {
   
    int sum=0,count=0,i,j;
    int x1=strlen(num1),x2=strlen(num2);
    int *y=(int *)malloc(sizeof(int)*(x1+x2));
    for(i=0;i<x1+x2;i++)
    {
        y[i]=0;//对数组赋值0,其实可以改为memset(y,0,sizeof(int)*(x1+x2));
    }
    for(i=x1-1;i>=0;i--)
    {
        for(j=x2-1;j>=0;j--)
        {
            y[i+j+1]+=(num1[i]-'0')*(num2[j]-'0');//关键步骤,实现上图功能
        }
    }
    for(i=x1+x2-1;i>=1;i--)
    {
          
            y[i-1]+=y[i]/10;
              y[i]=y[i]%10;//实现上图算法
    }
    char *result=(char *)malloc(sizeof(char)*(x1+x2+1));//开一个字符串数组为结果
    while(y[count]==0&&count<x1+x2-1)//避免出现0
    {
        count++;
    }
    while(count<x1+x2)
    {
        result[sum++]=y[count++]+'0';
    }
    result[sum]='\0';//结尾添\0
    return result;
}

从字符串相乘中学到了memset函数的用法,初始一块指定内存值赋值为某值。

**void *memset(void *s,int c,size_s),如假设我有一个int类型的已经动态分配内存的指针为int *value=(int *)malloc(sizeof(int)length);我想让这一内存所指向的值都赋值为1,则 memset(value,1,sizeof(int)length);就ok了

复习了链表,敲了一下带头节点和不带头节点的链表。

不带头节点的头插法,输出的数据和输入的数据顺序相反

在这里插入代码片#include<stdio.h>
#include<stdlib.h>
struct LNode
{
    int data;
    struct LNode *next;
};
struct LNode *head=NULL;//定义一个空的头指针
void inserthead(int num)//定义一个函数来读取数值
{

    struct LNode *newNode=(struct LNode*)malloc(sizeof(struct  LNode));
    newNode->data=num;
    newNode->next=head;
    head=newNode;
}
int main()
{
    int n,count=0;
    while(scanf("%d",&n)!=EOF)//多组输入
    {
        inserthead(n);//读入数值
    }
    struct LNode *temp=head;//用来遍历输出数值
   while(temp!=NULL)//temp不为空时运行
   {
       printf("%d ",temp->data);
       temp=temp->next;
   }
  return 0;
}

不带头节点尾插法,输出的数据和输入数据的顺序一样,我觉得用这个方法不如用带头节点的尾插法。

在这里插入代码片#include<stdio.h>
#include<stdlib.h>
struct LNode
{
    int data;
    struct LNode *next;
};
struct LNode *head=NULL;
void insertlast(int num)
{
    struct LNode *newNode=(struct LNode*)malloc(sizeof(struct LNode));
    newNode->data=num;
    newNode->next=NULL;
    if(head==NULL)
    {
        head=newNode;尾插法要判断一下头指针是否为空
    }
    else
    {
        struct LNode *lastNode=head;
        while(lastNode->next!=NULL)
        {
            lastNode=lastNode->next;
        }
        lastNode->next=newNode;
    }
}
int main()//主函数一样
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        insertlast(n);
    }
    struct LNode *temp;
    temp=head;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }
    return 0;
}

要执行删除操作的话,可以这样,因为未带头节点,删除起来要判断在首还是不在首的删除,删除起来有点麻烦,用bool类型来传回要删除值,找到key了就删除,返回1(true),没找到就返回0(false)

在这里插入代码片bool deleteNode(struct LNode **heade,int key)
{
    struct LNode *ne;
    if((*heade)->data==key)
    {
        ne=*heade;
       *heade=(*heade)->next;
       free(ne);
    }
    else{
            struct LNode *delete=*heade;
    while(delete->next!=NULL)
    {
        if(delete->next->data==key)
        {
            ne=delete->next;
            ne->next=delete->next;
            free(ne);
            return true;
        }
        else
        {
            delete=delete->next;
        }
    }
    return false;
    }
}

带头结点的头插法,输出的数据顺序和输入的相反,其头节点的数据域可以存储数据的个数,也可以不存储任何数据

在这里插入代码片#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
    int data;
    struct LNode *next;
}*Linklist,LNode;
void List_Head_Insert(LNode **head,int key)
{
    LNode *newnode=(LNode *)malloc(sizeof(LNode));
    newnode->data=key;
    newnode->next=(*head)->next;
    (*head)->next=newnode;

}
int main()
{
    int num;
   Linklist head=(LNode*)malloc(sizeof(LNode));
   head->next=NULL;
   while(scanf("%d",&num)!=EOF)
   {
       List_Head_Insert(&head,num);
   }
   LNode *temp=head->next;
   while(temp!=NULL)
   {
       printf("%d ",temp->data);
       temp=temp->next;
   }
   return 0;
}

带头节点的尾插法,输出的数据和输入的数据相反

在这里插入代码片#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
    int data;
    struct LNode *next;
}*Linklist,LNode;
void Last_insert(LNode *head,int key)
{
    LNode *temp=head;
    LNode *newnode=(LNode*)malloc(sizeof(LNode));
    newnode->data=key,newnode->next=NULL;
    while(temp->next!=NULL)
    {
    temp=temp->next;
    }
    temp->next=newnode;

}
int main()
{
    int num;
    Linklist head=(LNode *)malloc(sizeof(LNode));
    head->next=NULL;
    while(scanf("%d",&num)!=EOF)
    {
        Last_insert(head,num);
    }
    LNode *temp=head->next;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }
    return 0;
}

带头节点的删除法

在这里插入代码片void Node_delete(LNode *head,int number)
{
    LNode *temp=head,*delete_num;
    while(temp->next!=NULL)
    {
        if(temp->next->data==number)
        {
            delete_num=temp->next;
            temp->next=delete_num->next;
            free(delete_num);
        }
        else temp=temp->next;
    }
}

初步学了easyx,跟着up主敲了一下代码

想要有一个图形化窗口,可以用到easyx图形库,具体引入头文件
graphics.h

在这里插入代码片#include<graphics.h>//包含easyx头文件
#include<stdio.h>
void mGraphics()
{
	//RGB合成颜色 每个颜色值[0~256)左闭右开,红绿蓝
	//设置填充元素
	setfillcolor(RGB(10,125,36));
	//设置线条颜色
	setlinecolor(GREEN);
	//设置线条样式
	setlinestyle(PS_SOLID,5);//PS_SOLID可以转到定义看到更多线条样式
	//画圆
	circle(50, 50, 50);//无填充圆
	//有填充圆,有边框
	fillcircle(150, 50, 50);
	//实心圆,没有边框
	solidcircle(250, 50, 50);
}
int main()
{
	//创建图形窗口
	initgraph(640, 480,SHOWCONSOLE);//可以加SHOWCONSOLE,可以看到控制台消息
	mGraphics();
	while (1);//让创建的窗口一直显现
	closegraph();//关闭图形窗口
	return 0;
}

除了画图,还可以插入图片,具体实现

在这里插入代码片void drawImg()
{
	//图片类型IMAGE
	IMAGE imger;//不能直接赋值,必须通过函数加载
	/*
	 文件路径问题:1,相对路径 ./源文件所在是的目录,
	 2,绝对路径:包含盘符的路径
	*/
	loadimage(&imger, "./meme.jpg");
	putimage(0,0,&imger);//输出图片
}

想要在窗口中实现文字显示,具体代码

在这里插入代码片void drawStr()
{
	printf("Hello word!");//输出文字到控制台,在图形窗口看不到;
	/*outtextxy报错:
	问题:字符集不对
	解决方案:1,在字符串前面加上_T("str")
	 2,在字符串前面加一个大写的L
	 3,点击菜单栏->项目->属性->高级—>改为多字节字符集
	*/
	outtextxy(100, 100, "太未能阿斯蒂芬");//在图形窗口输出文字
	int score = 100;
	char str[10];
	outtextxy(100, 120, score);//输出A,要转入字符
	sprintf_s(str, "分数: %d", score);
	outtextxy(100, 130, str);
	
	setfillcolor(YELLOW);
	int x = 20, y = 20;
	fillrectangle(x, y, x+400, y+400);
	//文字为什么不见了?注意,图形绘制是有顺序的,有层级关系
	//设置文字的样式
	settextstyle(30, 0, "黑体");
	//把文字的背景干掉(设置背景模式为透明)
	setbkmode(TRANSPARENT);ppo
	//文字居中
	//文字的宽度和高度
	const char* strr = "吕卓远";//必须加上const
		int tw = textwidth(strr);
	int th = textheight(strr);
	int tx = (400 - tw) / 2;
	int ty = (400 - th) / 2;
	settextcolor(RGB(64, 56, 78));
	outtextxy(tx+x, ty+y, strr);
}

获取鼠标信息

在这里插入代码片void mouseEvent()
{
	//定义保存鼠标消息的结构
	MOUSEMSG msg;
	//获取鼠标信息
	if (MouseHit())//判断是否有鼠标消息,如果返回真1,否则0
	{
		msg = GetMouseMsg();
		//只有点击的时候显示的话
		printf("ps(%d,%d)\n", msg.x, msg.y);
		//判断左键,右键,还是中键
		switch(msg.uMsg)
		{
			case WM_LBUTTONDOWN://鼠标左键按下
				printf("WM_LBUTTONDOWN");
				break;
			case WM_RBUTTONDOWN:
				printf("WM_RBUTTONDOWN");
					break;
			case WM_MBUTTONDOWN:
				printf("WM_MBUTTONDOWN");
						break;

		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值