用C学习线性表

线性表是n个数据元素组成的有限序列,按照存储的方式分为顺序和链式。今天用C对顺序和链式分别做点练习。
(下面有很大一部分的代码是用vim写的,贴到博客上就有些格式问题了,不知道怎么解决。。)

纯C+顺序表 完成迷你选座系统

谁说简单数组不强大?
用简单的数组完成小型的选座系统建设:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct Node{
    int used;
    char sno[20],sname[20];
};
struct seat{
    struct Node st[MAX];
    int length;
};

/*  写入数据到顺序表中  */
void sql_init(struct seat *sql){
    FILE *fin=fopen("/home/edemon/Documents/data","r");
    if(fin==NULL){
        printf("the file can't be open.\n");
        return ;
    }
/*feof(FILE *stream)用来侦测是否读取到了文件尾,尾数stream为fopen()所返回之文件指针。
如果已到文件尾则返回非零值,其他情况返回0。  */
    for(int i=1;i<MAX;i++)  sql->st[i].used=0;
    while(feof(fin)==0){
        int d=-1;
    char s1[20],s2[20];
        fscanf(fin,"%d%s%s",&d,s1,s2);
        if(feof(fin)>0) break;
        strcpy(sql->st[d].sno,s1);
        strcpy(sql->st[d].sname,s2);
        sql->st[d].used=1;
        sql->length++;
    }
}

/*  展示座位的使用情况  */
void show(struct seat *sql){
    puts("");
    for(int i=1;i<MAX;i++){
       if(sql->st[i].used==0) printf("the No.%d seat is empty.\n",i);
       else {
           printf("the No.%d seat is used, information: %s %s\n",i,sql->st[i].sno,sql->st[i].sname);
       }
    }
}
/*  写入文件  */
void write(struct seat *sql){
    FILE *fout=fopen("/home/edemon/Documents/data","w");
    for(int i=1;i<MAX;i++){
        if(sql->st[i].used){
            fprintf(fout,"%-4d%10s%10s\n",i,sql->st[i].sno,sql->st[i].sname);
    }
    }
}
int main()
{
    /*FILE *fout;
    fout=fopen("/home/edemon/Documents/data","w");
    int id=1;
    char sno[20]="20130001",name[20]="Elena";
    fprintf(fout,"%-4d%10s%10s\n",id,sno,name);*/

    struct seat sql;
    sql.length=0;
    struct Node e;
    sql_init(&sql);
    int key;
    char number[20];
    while(1){
        //fflush(stdin);  /* 刷新标准输入缓冲区  */
    //system("clear");  /* for windows: system("cls"); it's to clear screen  */
    system("cat /home/edemon/Documents/data > /home/edemon/Documents/copy.txt");
    printf("******     欢迎使用选座系统     ******\n");
    printf("注意:非正常退出会使得文件中的数据丢失\n"); 
    printf("*      1-查看所有的座位使用信息      *\n");
    printf("*      2-查询某一座位的使用信息      *\n");
    printf("*      3-输号选座                    *\n");
    printf("*      4-释放座位                    *\n");
    printf("*      0-退出系统                    *\n");
    printf("**************************************\n");
    int ch;
    scanf("%d",&ch);
    switch(ch){
        case 0:
        write(&sql);
        return 0;
        case 1:
            show(&sql);
        //getchar();
        break;

        case 2:
            printf("请输入座位号: ");
        int d=0;
        scanf("%d",&d);
        if(sql.st[d].used==0) printf("the No.%d seat is empty\n",d);
        else {
            printf("the No.%d seat is used, information: %s %s\n",d,sql.st[d].sno,sql.st[d].sname);
        }
        break;

        case 3:
        enter:  printf("\n请输入空的座位号: ");  scanf("%d",&key);
        if(sql.st[key].used){
            printf("该座位已经被使用\n");
            goto enter;
            }
        printf("\n你的学号: ");  scanf("%s",e.sno);
        for(int i=1;i<MAX;i++){
            if(strcmp(sql.st[i].sno,e.sno)==0){
            printf("已有相同的学号正在使用座位No.%d,请确认没有输错学号。\
            输入3继续选座,输入其他数字退出。\n",i);
            scanf("%d",&key);
            if(key==3) goto enter;
            else goto final;
        }
        }
        printf("\n你的姓名:");  scanf("%s",e.sname);

            e.used=1;
        sql.st[key]=e;
        write(&sql);
        break;

        case 4:
        printf("请输入学号: ");   scanf("%s",number);
        for(int i=1;i<MAX;i++){
            if(strcmp(sql.st[i].sno,number)==0){
            sql.st[i].used=0;
        }
        }
        write(&sql);
        printf("谢谢你的合作\n");
            break;

        default:
        printf("请输入正确的指令。\n");
        break;
        }
    final:;
    }
    return 0;
}

关于指针

指针本身只是一个整数(地址),但其所指向的对象是丰富多样的,正因为寻址高效,所以处理数据很迅速。
源码:

#include <stdio.h>

int main(){
    int a[10]={1,2,3,4,5,6,7,8,9,10};
    int *p=&a;
    for(int i=0;i<10;i++){
    /*输出内存地址要用%p输出,%d输出范围比指针地址储存的范围小*/
        printf("%p %d\n",p,*p);
        p++;
    }
    return 0;
}
/*
输出:
0x7fff1b077870 1
0x7fff1b077874 2
0x7fff1b077878 3
0x7fff1b07787c 4
0x7fff1b077880 5
0x7fff1b077884 6
0x7fff1b077888 7
0x7fff1b07788c 8
0x7fff1b077890 9
0x7fff1b077894 10
*/

来看一个链表:

#include <stdio.h>
#include <stdlib.h>

typedef struct node{
    int val;
    struct node *next;
}*List,Node;
typedef struct node Node;
int main(){
    List p=(Node*)malloc(sizeof(Node));
    List p2=p;
    for(int i=1;i<11;i++){
        List temp=(Node*)malloc(sizeof(Node));
        temp->val=i;
        temp->next=NULL;
        p->next=temp;
        p=p->next;
    }
    p=p2->next;
    while(p){
        printf("%p %d\n",p,p->val);
        p=p->next;
    }
    return 0;
}
/*
output:
0xc71050 2
0xc71070 3
0xc71090 4
0xc710b0 5
0xc710d0 6
0xc710f0 7
0xc71110 8
0xc71130 9
0xc71150 10
*/

可以看出,结点的地址顺序和值的顺序保持一致的。

链表操作

链表逆序:

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
    int a;
    struct node *next;
}*List,list;
List create(){
    List head=(list*)malloc(sizeof(list));
    List p=head;
    for(int i=1;i<10;i++){
        List t=(list*)malloc(sizeof(list));
    t->a=i;
    t->next=NULL;
    p->next=t;
    p=p->next;
    }
    return head;
}
List reverse(List head){  // p3 p2 p1 
    List p1,p2,p3;
    p1=NULL;
    p2=head->next;
    p3=NULL;
    while(p2!=NULL){
        p1=p2->next;
    p2->next=p3;
    p3=p2;
    p2=p1;
    }
    return p3;
}
void print(List head){
     List p=head;
     while(p){
         printf("%3d",p->a);
     p=p->next;
     }
     puts("");
}
int main(){
    List head=create();
    print(head->next);
    head=reverse(head);
    print(head);
    return 0;
}
/*
output:
  1  2  3  4  5  6  7  8  9
  9  8  7  6  5  4  3  2  1
*/

链表删除节点

bool delet(List head,int i){
    int c=1;
    List p=head->next,q=head;
    while(p && c<i){
        p=p->next;
        q=q->next;
        c++;
    }
    if(c!=i) return false;
    q->next=p->next;
    free(p);
    return true;
}

链表增加节点(在i位置的后面插入值为number的结点):

bool insert(List head,int i,int number){
    int c=1;
    List p=head->next;
    while(p && c<i){
        p=p->next;
        c++;
    }
    if(c!=i) return false;
    List node=(list *)malloc(sizeof(list));
    node->a=number;
    node->next=p->next;
    p->next=node;
}

合并有序链表(两个有序链表合并后依然有序):

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
    int a;
    struct node *next;
}*List,list;
List create(int start,int end){
    List head=(list*)malloc(sizeof(list));
    List p=head;
    for(int i=start;i<=end;i++){
        List t=(list*)malloc(sizeof(list));
    t->a=i;
    t->next=NULL;
    p->next=t;
    p=p->next;
    }
    return head;
}
void print(List head){
     List p=head;
     while(p){
         printf("%3d",p->a);
     p=p->next;
     }
     puts("");
}
List merge(List h1,List h2){
    List p=(list*)malloc(sizeof(list));
    List r=p;
    h1=h1->next;
    h2=h2->next;
    while(h1 || h2){
        if(h1==NULL){
       p->next=h2;
       p=p->next;
       h2=h2->next;
       continue;
    }

    if(h2==NULL){
       p->next=h1;
       p=p->next;
       h1=h1->next;
       continue;
    }

    if(h1->a>h2->a){
       p->next=h2;
       p=p->next;
       h2=h2->next;
    }
    else {
       p->next=h1;
       p=p->next;
       h1=h1->next;
    }
    }
    return r;
}
int main(){
    List h1=create(1,10);
    List h2=create(6,15);
    List h=merge(h1,h2);
    print(h);
    return 0;
}
/*
output:
  0  1  2  3  4  5  6  6  7  7  8  8  9  9 10 10 11 12 13 14 15
*/

输出一个链表的中间结点:
1 2 3 4 5 6 7 8 9
5

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
    int a;
    struct node *next;
}*List,list;
List create(){
    List head=(list*)malloc(sizeof(list));
    List p=head;
    for(int i=1;i<10;i++){
        List t=(list*)malloc(sizeof(list));
    t->a=i;
    t->next=NULL;
    p->next=t;
    p=p->next;
    }
    return head;
}
void print(List head){
     List p=head;
     while(p){
         printf("%3d",p->a);
     p=p->next;
     }
     puts("");
}
/*   步长为1和步长为2的指针进行判断  */
List mid(List head){
    List one=head;
    List two=head;
    while(two){
       one=one->next;
       if(two) two=two->next;
       if(two) two=two->next;
    }
    return one;
}
int main(){
    List head=create();
    print(head->next);
    List m=mid(head);
    printf("%d\n",m->a);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值