原创 lightcity 光城 2018-12-02
17.求近似数
17.1 牛顿迭代法
如定积分、用牛顿迭代法或二分法或弦截法求多元方程的根
#include<stdio.h>
#include<math.h>
double func(double x)
{
return x*x*x*x - 3 * x*x*x + 1.5*x*x - 4.0;
}
double func1(double x)
{
return 4 * x*x*x - 9 * x*x + 3 * x;
}
int Newton(double *x,double precision,int maxcyc)
{
double x1, x0;
int k;
x0 = *x;
for (k = 0; k < maxcyc; k++)
{
if (func1(x0) == 0.0)
{
printf("迭代过程中导数为0!\n");
return 0;
}
x1 = x0 - func(x0) / func1(x0);
if (fabs(x1-x0) < precision || fabs(func(x1)) < precision)
{
*x = x1;
return 1;
}
else
{
x0 = x1;
}
}
printf("迭代次数超过预期!\n");
return 0;
}
int main()
{
double x, precision;
int maxcyc;
printf("输入初始迭代值x0:");
scanf("%lf",&x);
printf("输入最大迭代次数:");
scanf("%d", &maxcyc);
printf("迭代要求的精度:");
scanf("%lf", &precision);
if (Newton(&x, precision, maxcyc) == 1)
{
printf("该值附近的根为:%lf\n", x);
}
else
{
printf("迭代失败!\n");
}
return 0;
}
17.2 精简版
//精简版
#include<stdio.h>
#include<math.h>
double fun(double x)
{
return 2*x*x*x - 4*x*x + 3*x - 6;
}
double fun1(double x)
{
return 6*x*x - 8 * x + 3.0;
}
int main()
{
double x, x0, f,f1,precision;
printf("请输入初始x0:");
scanf("%lf",&x);
printf("请输入精度precision:");
scanf("%lf",&precision);
do
{
x0 = x;
f=fun(x0);
} while (fabs(x-x0)>= precision);
printf("%lf\n",x);
return 0;
}
17.3 二分法
1 确定区间[a,b],验证f(a)·f(b)<0
2 求区间(a,b)的中点x
3 判断
(1) 若f(a)·f(c)<0,则令b=x;
(2) 若f(x)·f(b)<0,则令a=x.4 判断f(x)是否达到精确度ξ:即若┃f(c)┃<ξ,则x=c就是使f(x)接近零点的近似值,否则重复2-4.
#include<stdio.h>
#include<math.h>
int main()
{
double func(double x);
double root(double a, double b);
root(-10,10);
return 0;
}
double func(double x)
{
return 2 * x*x*x - 4 * x*x + 3 * x - 6.0;
}
double root(double a, double b)
{
double x;
double a1=a, b1=b;
x = (a + b) / 2;
if(func(x)==0.0)
{
printf("该方程在%lf到%lf区间内的根为:%lf.\n",a1,b1,x);
return x;
}
else
{
while (fabs(a - b) > 1e-6)
{
if (func(a)*func(x) < 0)
b = x;
else
a = x;
x = (a + b) / 2;
}
}
printf("该方程在%lf到%lf区间内的根为:%lf.\n", a1, b1, x);
return x;
}
17.4 弦截法
函数方程:
y - f2 = (f2 - f1) / (x2 - x1)(x - x2)
化简得:
x=(f2x1-f1x2)/(f2-f1)
#include<stdio.h>
#include<math.h>
double xpoint(double x1, double x2); //弦与x轴的交点横坐标
double root(double x1, double x2); //求根函数
double f(double x); //求x点的函数值
int main()
{
double x1, x2, f1, f2, x;
do
{
printf("请输入x1,x2:");
scanf("%lf,%lf",&x1,&x2);
f1 = f(x1);
f2 = f(x2);
} while (f1*f2>=0); //当循环运算到f(x1)*f(x2)>=0时(0是必要条件参数),即f(x1)、f(x2)同符号,且任一个接近于0时,意味着与x轴接近相交,此时存在一个方程实根。
x = root(x1,x2);
printf("方程的一个解为:%.2f\n",x);
return 0;
}
double xpoint(double x1, double x2)
{
double x = 0;
x = (x1*f(x2)-x2*f(x1)) / (f(x2)-f(x1));
return x;
}
double root(double x1,double x2)
{
double x, y, y1, y2;
y1 = f(x1);
y2 = f(x2);
do
{
x = xpoint(x1,x2);
y = f(x);
if (y*y1 > 0)
{
x1 = x;
y1 = y;
}
else
{
x2 = x;
y2 = y;
}
} while (fabs(y)>=0.00001);
return x;
}
double f(double x)
{
double y = 0;
y = x*x*x - 5 * x*x + 16 * x - 80;
return y;
}
18.矩阵运算及二维数组
18.1 求两个矩阵之和、之积
#include<stdio.h>
#define N 2
int main()
{
void print(int(*a)[N]);
void vx(int(*a)[N], int(*b)[N]);
int i, j;
int a[N][N],b[N][N];
printf("输入两个矩阵:\n");
printf("矩阵1:\n");
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
scanf("%d",&a[i][j]);
printf("---------\n");
print(a);
printf("矩阵2:\n");
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
scanf("%d", &b[i][j]);
printf("---------\n");
print(b);
vx(a,b);
return 0;
}
void vx(int (*a)[N],int (*b)[N])
{
void print(int(*a)[N]);
int i,j,k,res;
int c[N][N],d[N][N];
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
{
res = 0;
c[i][j] = a[i][j] + b[i][j];
for(k=0;k<N;k++)
res += a[i][k] * b[k][j];
d[i][j]=res;
}
printf("两矩阵相加:\n");
print(c);
printf("两矩阵相乘:\n");
print(d);
}
void print(int (*a)[N])
{
int i,j;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
printf("%d ",a[i][j]);
printf("\n");
}
}
18.2 二维数组
二维数组某位置上的元素在该行上最大,该列上最小
#include<stdio.h>
int main()
{
int a[4][5];
int i, j, k, m;
for (i = 0; i < 4; i++)
for (j = 0; j < 5; j++)
scanf("%d",&a[i][j]);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 5; j++)
{
//扫描行,确定行中最大值
for (k = 0; k < 5; k++)
{
if (a[i][j] < a[i][k])
{
break;
}
}
if (k == 5)
{
//扫描列,确定列中最小值
for (m = 0; m < 4; m++)
{
if (a[i][j] > a[m][j])
break;
}
if (m == 4)
printf("满足值:%d ",a[i][j]);
}
}
}
return 0;
}
19.位运算及应用
19.1 位运算
1.与 &
1&0=0;0&0=0;1&1=1;2.或 |
1|0=1;0|0=0;1|1=1;3.非 ~
~1=-2
~16=-17
00010000 16二进制数
11101111 16二进制数取非运算
取反+1即:
00010000+1=00010001=-174.异或
1^0=1;0^0=0;1^1=0
19.2 一个字节中被置为1的位的个数
#include<stdio.h>
int main()
{
int sum = 0;
//题中给出一个字节,则占8位,取值范围为0~255
int a;
printf("请输入一个字节的数,以十进制输入:\n");
scanf("%d",&a);
if (a < 0 || a>255)
{
printf("error\n");
return 1;
}
int i, k=1;
for (i = 1; i < 9; i++)
{
if (a == (a | k))
sum++;
k *= 2;
}
printf("共%d位\n",sum);
return 0;
}
20.排序算法
20.1 快速排序
void sort(int *p, int low, int high)
{
if (low > high)
return;
int temp, i, j, t;
temp = p[low];
i = low;
j = high;
while (i < j)
{
while (i<j&&p[j]>=temp)
j--;
while (i < j&&p[i] <= temp)
i++;
if (i < j)
{
t = p[i];
p[i] = p[j];
p[j] = t;
}
}
p[low] = p[i];
p[i] = temp;
sort(p,low,i-1);
sort(p,i+1,high);
}
20.2 冒泡排序
void sort(int *p, int n)
{
int i, j;
int t;
for (i = 0; i < n - 1; i++)
{
for(j=0;j<n-i-1;j++)
{
if (p[j] > p[j + 1])
{
t = p[j];
p[j] = p[j+1];
p[j + 1] = t;
}
}
}
}
20.3 选择排序
void sort(int *p, int n)
{
int i, j, k, temp;
for (i = 0; i < n-1; i++)
{
k = i;
for (j = i; j < n; j++)
{
if (p[k] > p[j])
k = j;
}
temp = p[i];
p[i] = p[k];
p[k] = temp;
}
}
20.4 直接插入排序
void sort(int *p, int n)
{
int i,j,k,t;
for(i=1;i<n;i++) //注意从第2个元素操作
{
if(p[i]<p[i-1])
{
t=p[i];
for(j=i-1;j>=0&&p[j]>t;j--)
{
p[j+1]=p[j];
}
}
p[j+1]=t;
}
}
//换成字符操作
void sort(char *p)
{
int i,j,n;
char ch;
n=strlen(p);
for(i=i;i<n;i++)
{
ch=p[i];
j=i-1;
while((j>=0)&&(ch<p[j]))
{
p[j+1]=p[j];
j--;
}
p[j+1]=ch;
}
}
21.链表
21.1 单链表之增删改查
/*单链表*/
#include<stdio.h>
#include<malloc.h>
typedef struct Node {
int data;
struct Node *PNext;
}Node, *PNode;
#define ERROR 0
#define OK 1
PNode create_list()
{
int len, i;
printf("请输入链表的长度:len=\n");
scanf("%d",&len);
PNode PHead = (PNode)malloc(sizeof(Node));
PHead->PNext = NULL;
PNode PTail=PHead;
for (i = 0; i < len; i++)
{
int val;
printf("请输入第%d个元素的值:",i+1);
scanf("%d",&val);
PNode PNew = (PNode)malloc(sizeof(Node));
PNew->data = val;
PNew->PNext = NULL;
PTail->PNext=PNew;
PTail = PNew;
}
return PHead;
}
void outLink(PNode pHead)
{
PNode p = pHead->PNext;
while (p)
{
printf("%d ",p->data);
p = p->PNext;
}
putchar('\n');
}
PNode reverse(PNode pHead)
{
PNode p = pHead->PNext;
PNode q,r;
q = p->PNext;
p->PNext = NULL;
while (q)
{
r = p;
p = q;
q = p->PNext;
p->PNext = r;
}
pHead->PNext = p;
return pHead;
}
int list_num(PNode pHead)
{
int num = 0;
PNode p = pHead->PNext;
while (p)
{
num++;
p = p->PNext;
}
return num;
}
//pos从1开始
/*
12345
有6个插入位置
*/
int insert_list(pnode phead, int val, int pos)
{
int i;
pnode p = phead->pnext;
int length = list_num(p);
if (pos<1 || pos>length+2)
return error;
else
{
i = 0;
//定位到pos前一位,在下标pos-1处插入结点,需要知道前一结点
while (p&&i < pos - 2)
{
i++;
p = p->pnext;
}
if (p||(i == pos - 2))
{
pnode pnew = (pnode)malloc(sizeof(pnode));
pnew->data = val;
if (pos == 1)
{
pnew->pnext = p;
phead->pnext = pnew;
}
else if (pos == length+2)
{
p->pnext = pnew;
pnew->pnext=null;
}
else
{
pnew->pnext = p->pnext;
p->pnext = pnew;
}
length++;
return ok;
}
else
return error;
}
}
int insert_list(PNode pHead, int val, int pos)
{
PNode p = pHead;
int length = list_num(p),i;
if (pos<0 || pos>length ||!p)
return ERROR;
else
{
i = -1;
while (p&&i < pos - 1)
{
i++;
p=p->PNext;
}
if (i == pos - 1 || p)
{
PNode PNew = (PNode)malloc(sizeof(PNode));
PNew->data = val;
if (i == -1)
{
PNew->PNext = pHead->PNext;
pHead->PNext = PNew;
}
else if (pos == length)
{
p->PNext = PNew;
PNew->PNext = NULL;
}
else
{
PNew->PNext = p->PNext;
p->PNext = PNew;
}
length++;
return OK;
}
else
return ERROR;
}
}
//删除,根据结点值删除
int delData(PNode pHead, int *val)
{
int length = list_num(pHead);
PNode p = pHead,q;
if (!p)
return ERROR;
while (p->PNext!=NULL)
{
if (p->PNext->data == *val)
{
q = p->PNext;
p->PNext = p->PNext->PNext;
free(q);
}
else
p = p->PNext;
}
return OK;
}
//删除,按照位置删除,且pos从1开始
int delpos(PNode pHead, int pos)
{
PNode q = pHead;
PNode p = q->PNext;
int length = list_num(pHead);
if (pos<1 || pos>length)
return ERROR;
else
{
int i = 1;
while (i < pos - 1)
{
i++;
q = p;
p = p->PNext;
}
if (pos == 1)
pHead->PNext = pHead->PNext->PNext;
else if (pos == length)
q->PNext = NULL;
length--;
return OK;
}
}
//或者pos从0开始计算
/*12345
有0~length范围可插入
*/
int main()
{
int num;
PNode PHead = create_list();
outLink(PHead);
num = list_num(PHead);
putchar('\n');
printf("共有%d个结点.\n", num);
PNode rp = reverse(PHead);
outLink(rp);
int val;
printf("请输入插入结点的值:");
scanf("%d", &val);
int pos;
printf("请输入插入结点的位置(从1开始):");
scanf("%d", &pos);
int flag = insert_list(rp, val, pos);
if (flag == 1)
{
printf("插入结点成功,共%d个结点\n", list_num(rp));
outLink(rp);
}
else
printf("插入失败.\n");
int data;
printf("请输入要删除的结点值:");
scanf("%d", &data);
int f = delData(rp, &data);
if (f == 1)
{
printf("删除%d成功!\n", data);
outLink(rp);
}
else
printf("删除结点不存在!\n");
int delposi;
printf("请输入要删除的位置:");
scanf("%d", &delposi);
int f1 = delpos(rp, delposi);
if (f1 == 1)
{
printf("删除第%d个位置成功!\n", delposi);
outLink(rp);
}
else
printf("删除位置不存在!\n");
}
21.2 头插法
头插法思路:先判断是否为head结点,若为head结点,则将新造的结点先赋值,然后链接在head后面,并将此时结点的next设为空,因为此时表示末尾结点,否则会出错!!!
此次结束后,将p指向q所指的结点,然后新造结点将q结点的next链接到p,在往前,最后用将p结点链接至head结点后面即可!
node * createlist()
{
int n;
node *head = (node *)malloc(sizeof(node));
node *p = head;
head->next = NULL;
if (head == NULL)
{
printf("申请空间失败!\n");
return NULL;
}
else
{
printf("请输入结点个数,n=");
scanf("%d",&n);
int i,num;
for (i = 0; i < n; i++)
{
printf("请输入第%d个结点数值:\n",i+1);
scanf("%d",&num);
node *q = (node *)malloc(sizeof(node));
if (p == head)
{
head->next = q;
q->data = num;
q->next = NULL;
}
else
{
q->data = num;
q->next = p;
}
p = q;
}
head->next = p;
}
return head;
}
21.3 链表逆置
NODE *reverseList(NODE *h)
{
NODE *p, *q, *r;
p = h;
if (!p)
return NULL;
q = p->next;
p->next = NULL;
while (q)
{
r = q->next;
q->next = p;
p = q;
q = r
return p;
}