C语言常见算法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43138570/article/details/102564709

常见算法
一、数组排序
选择排序、插入排序、交换排序

1.直接插入排序
将待排序的数按大小,插到前面排好数据的适当位置。

 11,8,1,10,7,4,12,2,3,6,5,9

实现方法:在已排数据中,只要比待排大,则向后移动一格,在这个大数据倒出一个空格,直到比这个待排的小为止,最后将待排的插入到空格处.

 int main(int argc,char **argv){
     int a[]={1,12,11,8,10,7,4,2,3,6,5,9};
     int i,j,n=12;
     for(i=1;i<n;i++){//要排数的下标
        int tmp=a[i]; //将待排的元素保存到临时变量中
        j=i-1;
        while(j>=0 && a[j]>tmp){ //j代表已排的下标
            a[j+1]=a[j]; //元素向后移动
            j--;   //下标递减
        }
        a[j+1]=tmp;//赋给空出位置的元素
     }
     for(i=0;i<n;i++) printf("%d ",a[i]);
 }

2.直接选择排序法
是从待排序的数据中选出最小的值,顺序存放在已排序的数据后面

int main(int argc,char **argv){
    int a[]={11,8,1,10,7,4,12,2,3,6,5,9};
    int i,j,n=12;
    for(i=0;i<n;i++){ //i代表已排序后面的数的下标
       int min=i;
       for(j=i;j<n;j++){//在待排序数中找到最小的下标
          if (a[min] > a[j]) min=j;
       }
       //如果找到的最小的和已排序后面数的值不同,则换
       if (a[i]>a[min]){
       	  int tmp=a[i];
          a[i]=a[min];
          a[min]=tmp;
       }
    }
    for(i=0;i<n;i++) printf("%d ",a[i]);
}

3.冒泡排序(交换排序)

两两比较待排序数,交换不满足顺序的两个数

int main(int argc,char **argv){
    int a[]={11,8,1,10,7,4,12,2,3,6,5,9};
    int i,j,n=12;

    for(i=1;i<n;i++){ //i代表第i轮 共n-1轮
        for(j=0;j<n-i;j++){ //j代表下标 共比较n-i次
           if (a[j] >a[j+1]){
              int tmp=a[j];
              a[j]=a[j+1];
              a[j+1]=tmp;
           }
        } 
    } 
    for(i=0;i<n;i++) printf("%d ",a[i]);
}    

二、链表排序
1.改内容
不可取

2.改变链表的链接 (了解)
struct Num{
int n;
struct Num *next;
} *head,*tail;

struct Num* creat(int n){
   struct Num *p=(struct Num*)malloc(sizeof(struct Num));
   p->n=n;
   p->next=NULL;
   return p;
}

void add(struct Num *p){
   if (head==NULL) head=p;
   else tail->next=p;
   tail=p;
}

void print(){
   struct Num *p=head;
   while(p!=NULL){
      printf("%d ",p->n);
      p=p->next;
   }
   printf("\n");
}

void sort(){
   struct Num *nhead=NULL,*ntail;
   while(head!=NULL){
       //找最小的地址
       struct Num *min=head,*premin=NULL,*p=head,*p1=NULL;
       while(p!=NULL){
          if (min->n >p->n) {
              premin=p1; //最小值的前一个地址
              min=p;     //最小值的地址
          }
          p1=p;
          p=p->next;
       }
      //将结构体从原链中摘除
       if (premin==NULL) head=min->next;//如果要摘的是头,则确定新头
       else premin->next=min->next;
       //新链尾插
       if (nhead==NULL) nhead=min;
       else ntail->next=min;
       ntail=min;
   }
   //将新的头和尾,重新保存到原的头和尾变量内
   head=nhead;
   tail=ntail;
}
  
int main(int argc,char **argv){
    int a;
    while(1){
       scanf("%d",&a);
       if (a==-1) break;
       struct Num* p=creat(a);
       add(p);
    }
    //------------------
    print();
    sort();
    print();
}

2.建立索引表 ****

   struct Num** sort(int *gs){
      //将结构体的地址保存到数组中
      struct Num *p=head,**a=(struct Num**)malloc(count * 4);//索引表
      int i=0,j;
      while(p!=NULL) {
          a[i++]=p;
          p=p->next;
      }
      //排序
      for (i=1;i<count;i++){
         for(j=0;j<count-i;j++){
           if (a[j]->n > a[j+1]->n){
              struct Num *tmp=a[j];
              a[j]=a[j+1];
              a[j+1]=tmp;
           }
         }
      }
      *gs=count;
      return a;
   }
   
   int main(int argc,char **argv){
       int a;
       while(1){
          scanf("%d",&a);
          if (a==-1) break;
          struct Num* p=creat(a);
          add(p);
       }
       //------------------
       print();
       int i,n;
       struct Num **b=sort(&n);
       for(i=0;i<n;i++) printf("%d ",b[i]->n);
       free(b);
   }

三、查找

1.无序数组查找
1,11,8,10,7,4,12,2,3,6,5,9
找到 3 并打印
依次遍历(即从头到尾来比较)

2.有序数组查找
1 2 3 4 5 6 7 8 9 10 11 12

二分法,也称折半法
int main(int argc,char **argv){
int a[]={1,2,3,4,5,6,7,8,9,10,11,12};
int b=atoi(argv[1]);
int min=0,max=11,mid;
int sign=0; //1代表找到 0没找到
while(min<=max && !sign){
mid=(min+max)/2;
if (a[mid]b) sign=1; //找到了 mid就是要找的值的下标
else if (a[mid] > b) max=mid-1;
else min=mid+1;
}
if (sign
1) printf("---- %d\n",a[mid]);
else printf(“没找到\n”);
}

3.链表查找

1)无序链表
遍历
2)有序链表
遍历
3)索引表(哈希)
同数组二分法

4.将链表保存到文件
struct Num{
int n;
struct Num *next;
} *head,*tail;

 int count;
 struct Num* creat(int n){
    count++;
    struct Num *p=(struct Num*)malloc(sizeof(struct Num));
    p->n=n;
    p->next=NULL;
    return p;
 }
 void add(struct Num *p){
    if (head==NULL) head=p;
    else tail->next=p;
    tail=p;
 }
 
 void print(){
    struct Num *p=head;
    while(p!=NULL){
       printf("%d ",p->n);
       p=p->next;
    }
    printf("\n");
 }
 int msave(char *file){
    FILE *fp=fopen(file,"w");
    if (fp==NULL) return -1;
    struct Num *p=head;
    while(p!=NULL){
       fwrite(p,sizeof(struct Num),1,fp);
       p=p->next;
    }
    fclose(fp);
    return 0;
 }
 int mopen(char *file){
    FILE *fp=fopen(file,"r");
    if (fp==NULL){
        printf("---- open err=%s\n",strerror(errno));
        return -1;
    }
    fseek(fp,0,2);
    int i=0,n=ftell(fp)/sizeof(struct Num);
    fseek(fp,0,0);
    while(i<n){
       struct Num *p=(struct Num*)malloc(sizeof(struct Num));
       fread(p,sizeof(struct Num),1,fp);
       p->next=NULL;
       add(p);
       i++;
    }
    fclose(fp);
    return 0;
 }
 int main(int argc,char **argv){
    int err= mopen(argv[1]);
    if (err==0){
        print();
    }
    else {//失败
         int a;
         while(1){
            scanf("%d",&a);
            if (a==-1) break;
            struct Num* p=creat(a);
            add(p);
         }
         msave(argv[1]);
    }
 }

猜你喜欢

转载自blog.csdn.net/weixin_43138570/article/details/102564709