Day16、文件拷贝、数据结构(逻辑结构、物理结构)顺序物理结构、链式物理结构

来源:互联网 发布:windows最新软件版本 编辑:程序博客网 时间:2024/05/22 09:39

复习文件: 编写程序实现文件拷贝功能

./a.out  路径一    路径二

./a.out  a.txt      b.txt     a已存在,b是复制出来的

 

 

  1#include<stdio.h>

  2int main(int argc,char *argv[]/* **argv */){

 3     int size=0;

 4     FILE*p_src=NULL,*p_dest=NULL;

 5     char buf[100]={0};

 6     if(argc<3){

 7         printf("命令错误\n");

 8         return 0;

 9     }

 10    p_src=fopen(*(argv+1),"rb");

 11    if(!p_src){

 12        printf("原始文件打开失败\n");

 13        return 0;

 14     }

 15    p_dest=fopen(*(argv+2),"wb");

 16    if(!p_dest){

 17         printf("目标文件打开失败\n");

 18        fclose(p_src);

 19        p_src=NULL;

 20        return 0;

 21     }

 22    while(1){

 23        size=fread(buf,sizeof(char),100,p_src);

24         //从文件中拿出100个字节放到存储区

 25        if(!size){

 26            break;

 27        } // 若最后一字不足100字节,两个文件大小就不一样,所以用size来算字节

 28        fwrite(buf,sizeof(char),size,p_dest);

 29     }

 30    fclose(p_dest);

 31    p_dest=NULL;

 32    fclose(p_src);

 33    p_src=NULL;

 34    return 0;

 35 }

 

 

数据结构

数据结构研究如何使用存储区解决问题

算法研究解决一些常见问题的方法

数字之间的关系可以从两个完全不同的角度进行描述

逻辑关系(逻辑结构):描述数字之间的关系,和计算机无关。

物理关系(物理结构):描述存放数字的存储区之间的关系。

逻辑结构分为如下几种:

1、 集合结构:所有数字元素是一个整体,它们之间没有其他关系

2、 线性结构:可以用一条有顺序的线把所有数字连接起来

3、 树状结构:所有数据都是从一个数据开始向一个方向扩展出来,任何数据都可以扩展出多个其他数据

4、 图形结构:图形结构的数据元素是多对多的,任何两个数字之间可以有直接联系,所有数字之间的联系没有统一方向

物理结构有以下两种:

1、  顺序结构:所有存储区在内存里连续排列(数组和动态分配内存都是顺序结构的例子) 顺序结构中每个存储区都有一个编号(内存地址),可以根据编号直接找到对应的存储区,(数组)根据编号找到存储区的方法叫做随机访问。顺序结构支持随机访问能力。缺点:顺序结构中存储区个数(内存大小)很难调整,可能造成内存的浪费。顺序结构不适合进行插入或删除文件。

例: 在顺序结构中插入数字

  1#include<stdio.h>

  2void insert(int *p_num,int size,int num){

 3     int tmp=num,num1=0,tmp1=0;

 4    for(num1=0;num1<=size-1;num1++){ 

 5        if(tmp<*(p_num+num1)){

 6             tmp1=tmp;

 7             tmp=*(p_num+num1);

 8             *(p_num+num1)=tmp1;

 9         }

 10        else if(/*tmp>*(p_num+num1)&&*/num1&&*(p_num+num1-1)>*(p_num+num1)){

       // 考虑数组的第一个元素不能与之前存储区(不在数组里)的数值比较,并且考虑到临时存储区tmp与后面0的比较

 11            tmp1=tmp;

 12            tmp=*(p_num+num1);

 13            *(p_num+num1)=tmp1;

 14            break;

 15        }

 16     }

 17 }

 18int main(){

 19    int arr[20]={2,6,12,14,17,21,23,31,35,37};

 20    int num=0;

 21    insert(arr,20,27);

 22    for(num=0;num<=19;num++){

 23        printf("%d ",arr[num]);

24     }

 25    printf("\n");

 26    return 0;

 27 }

从顺序结构中删除数字

  1#include<stdio.h>

  2void remove_num(int *p_num,int size,int num){

 3     int num1=0;

 4    for(num1=0;num1<=size-1;num1++){

 5        if(num<*(p_num+num1)){

 6            *(p_num+num1-1)=*(p_num+num1);

 7         }

 8         elseif(num1&&*(p_num+num1)<*(p_num+num1-1)){

 9             *(p_num+num1-1)=*(p_num+num1);

 10            break;

 11        }

 12     }

 13 }

 14int main(){

 15    int arr[20]={2,6,12,14,17,21,23,31,35,37};

 16    int num=0;

 17    remove_num(arr,20,37);

 18    for(num=0;num<=19;num++){

 19        printf("%d ",arr[num]);

 20     }

 21    printf("\n");

 22    return 0;

 23 }

2链式物理结构:由多个无关的存储区构成,任何两个存储区之间可以用指针连接

链式物理结构中每个存储区叫做一个节点

单向线性链式物理结构中任何两个节点之间都有前后关系(每个节点里只包含一个指针)

单向线性链式物理结构中最后一个节点里的指针必须是空指针

例:

  1#include<stdio.h>

  2typedef struct node{

 3     int num;

 4     struct node *p_next;

  5 }node;

  6int main(){

 7     nodenode1={1},node2={5},node3={12};

 8     node1.p_next=&node2;

 9     node2.p_next=&node3;

 10    return 0;

 11 }

链式物理结构不直接支持随机访问能力

在所有节点前增加一个无效头结点,在所有结点后增加一个无效尾结点,这样可以简化程序的编写

1 #include<stdio.h>

  2typedef struct node{

 3     int num;

 4     struct node *p_next;//指向结构体类型的指针

  5}node;

  6int main(){

 7     nodenode1={1},node2={5},node3={12},head={0},tail={0};

 8     node1.p_next=&node2;

 9     //结点1的指针指向结点2的地址(结构体和int,char是并行关系,都用&表示其地址)

 10    node2.p_next=&node3;

 11    head.p_next=&node1;

 12    node3.p_next=&tail;

 13    return 0;

 14 }

  遍历打印

  1#include<stdio.h>

  2typedef struct node{

 3     int num;

 4     struct node *p_next;//指向结构体类型的指针

  5}node;

  6int main(){

 7     nodenode1={1},node2={5},node3={12},head={0},tail={0};

 8     node *p_node=NULL;

 9     node1.p_next=&node2;

 10    //结点1的指针指向结点2的地址(结构体和int,char 是并行关系,都用&表示其地

    址)

 11    node2.p_next=&node3;

 12    head.p_next=&node1;

 13    node3.p_next=&tail;

 14    for(p_node=&head;p_node!=&tail;p_node=p_node->p_next){

 15        node *p_first=p_node;

 16        node *p_mid=p_first->p_next;

 17        node *p_last=p_mid->p_next;

 18        if(p_mid!=&tail){    //p_first->next!=NULL;只要有数字

 19             printf("%d",p_mid->num);

 20        }

 21     }

 22    return 0;

 

打印编号为2的数字:(12)

  1#include<stdio.h>

  2typedef struct node{

 3     int num;

 4     struct node *p_next;//指向结构体类型的指针

  5}node;

  6int main(){

 7     int cnt=0;

 8     nodenode1={1},node2={5},node3={12},head={0},tail={0};

 9     node *p_node=NULL;

 10    node1.p_next=&node2;

 11    //结点1的指针指向结点2的地址(结构体和int,char 是并行关系,都用&表示其地

    址)

 12    node2.p_next=&node3;

 13    head.p_next=&node1;

 14    node3.p_next=&tail;

 15    for(p_node=&head;p_node!=&tail;p_node=p_node->p_next){

 16        node *p_first=p_node;

 17        node *p_mid=p_first->p_next;

 18        node *p_last=p_mid->p_next;

 19        if(p_mid!=&tail&&cnt==2){

 20            printf("数字是%d\n",p_mid->num);

 21        }

 22        cnt++;

23     }

 24    return 0;

 25 }

插入:将7插进去,按大小排列

  1#include<stdio.h>

  2typedef struct node{

 3     int num;

 4     struct node *p_next;//指向结构体类型的指针

  5}node;

  6int main(){

 7     int cnt=0;

 8     node node1={1},node2={5},node3={12},head={0},tail={0},node4={7};

 9     node *p_node=NULL;

 10    node1.p_next=&node2;

 11    //结点1的指针指向结点2的地址(结构体和int,char 是并行关系,都用&表示其地

    址)

 12    node2.p_next=&node3;

 13    head.p_next=&node1;

 14    node3.p_next=&tail;

 15     for(p_node=&head;p_node!=&tail;p_node=p_node->p_next){

 16        node *p_first=p_node;

 17        node *p_mid=p_first->p_next;

 18        node *p_last=p_mid->p_next;

 19        if(p_mid==&tail||p_mid->num>node4.num){

 20            p_first->p_next=&node4;

 21            node4->p_next=p_mid;

 22            break;

23         }

 24     }

 25    for(p_node=&head;p_node!=&tail;p_node=p_node->p_next){

 26        node *p_first=p_node;

 27        node *p_mid=p_first->p_next;

 28        node *p_last=p_mid->p_next;

 29        if(p_mid!=&tail){

 30            printf("%d ",p_mid->num);

 31        }

 32     }

 33    printf("\n");

 34    return 0;

 35 }

删除:将5删去

  1#include<stdio.h>

  2typedef struct node{

 3     int num;

 4     struct node *p_next;//指向结构体类型的指针

  5}node;

  6int main(){

 7     // int cnt=0;

 8     nodenode1={1},node2={5},node3={12},head={0},tail={0};

 9     node *p_node=NULL;

 10    node1.p_next=&node2;

 11    //结点1的指针指向结点2的地址(结构体和int,char 是并行关系,都用&表示其地

    址)

 12    node2.p_next=&node3;

 13    head.p_next=&node1;

 14    node3.p_next=&tail;

 15    for(p_node=&head;p_node!=&tail;p_node=p_node->p_next){

 16        node *p_first=p_node;

 17        node *p_mid=p_first->p_next;

 18        node *p_last=p_mid->p_next;

 19         if(p_mid!=&tail&&p_mid->num==5){

 20            p_first->p_next=p_last;

 21            break;

 22        }

23     }

 24    //遍历打印

 25    for(p_node=&head;p_node!=&tail;p_node=p_node->p_next){

 26        node *p_first=p_node;

 27        node *p_mid=p_first->p_next;

 28        node *p_last=p_mid->p_next;

 29        if(p_mid!=&tail){

 30            printf("%d ",p_mid->num);

 31        }

 32     }

 33    printf("\n");

 34    return 0;

 35 }

 

图示:

First Mid Last 三个指针

Mid指针一般指向有效结点,所以,对mid进行操作

如果插入一个数,插到firstmid之间

如果删除某一个数,让mid指向删除数的结点,直接让first=last

 


0 0