如何提高编程能力?(中)

  • 2019 年 10 月 5 日
  • 筆記

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("该值附近的根为:%lfn", 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("%lfn",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("方程的一个解为:%.2fn",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=-17
  • 4.异或 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("errorn");          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;  }