• 线性表学习笔记


      最近学习数据结构的线性表,主要是借助教材《数据结构》(C语言版)那本。在课堂上学习的时候没有认真听讲,唉,,,书上面的程序没有写过,知识了解大概,现在开始准备面试,数据结构是首先要拿下的基础知识,所以开始了数据结构的再学习,下面是线性表部分,下面还会有栈、队列、串、数组、树、图、排序、查找等等。程序不一定完全正确,都是用C语言实现的书上的例子,没有包括所有的线性表性质,但基本上实现了线性表基本操作(顺序和链式),欢迎大家提出宝贵意见。

    下面附上练习源码(仅作参考)

      1 /**
      2  * 线性表的各种操作
      3  * 对应《数据结构(C语言版)》的教材
      4  * @author:zhaoyafei
      5  * @aime:2015-6-16
      6  */
      7 //引入必要头文件
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 //约定的宏定义  
     11 #define TRUE 1
     12 #define FALSE 0
     13 #define OK 1
     14 #define ERROR 0
     15 #define INFEASIBLE -1
     16 #define OVERFLOW -2
     17 
     18 //初始空间分配量
     19 #define LIST_INIT_SIZE 100
     20 //空间分配的增量
     21 #define LISTINCREMENT  10
     22 //Status是函数的类型,其值是函数结果的状态码
     23 typedef int Status;
     24 //数据元素约定为ElemType,可以自己定义
     25 typedef int ElemType;
     26 
     27 //线性表的顺序实现
     28 typedef struct{
     29     ElemType * elem;  //存储空间的基地址
     30     int      lenght;  //当前的长度
     31     int      listsize;//当前分配的存储容量
     32 }SqList;
     33 
     34 //线性表的链式实现
     35 typedef struct LNode{
     36     ElemType     data; //存储数据
     37     struct LNode * next; //递归定义,指向下一个元素
     38 }LNode,*LinkList;//结构体类型指针
     39 
     40 //双向链表的实现
     41 typedef struct DuLNode{
     42     ElemType data;
     43     struct DuLNode *prior;
     44     struct DuLNode *next;
     45 }DulNode, *DuLinkList;
     46 
     47 /*************************顺序实现***************************/
     48 //构造空的线性表
     49 Status InitList(SqList &L, int lenght){
     50     if (lenght == 0) {
     51         lenght = LIST_INIT_SIZE;
     52     }
     53     L.elem = (ElemType *)malloc(lenght * sizeof(ElemType));
     54 
     55     if(!L.elem){
     56         exit(OVERFLOW);  //分配存储空间失败
     57     }
     58     L.lenght = 0;        //初始空表长度为0
     59     L.listsize = lenght ;//初始存储容量为100
     60     return OK;
     61 }
     62 
     63 //在第i的位置插入元素e
     64 Status ListInse_Sq(SqList &L, ElemType e, int i){
     65     ElemType *p, *q;
     66     if(i < 0 || i > L.lenght){
     67         //i的值不合法
     68         return ERROR;
     69     }
     70     if (L.lenght >= L.listsize) {
     71         //空间不够,重新分配存储空间
     72         ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize + LISTINCREMENT)*sizeof(ElemType));
     73         if(!newbase){
     74             return OVERFLOW;            //存储分配失败
     75         }
     76         L.elem = newbase;               //记录新基值
     77         L.listsize += LISTINCREMENT;    //增加存储容量
     78     }
     79     q = &L.elem[i];                     //得到元素插入的位置
     80     for (p = &L.elem[L.lenght]; p >= q; --p) {
     81         *p = *(p-1);                    //把插入位置元素之后的元素往后移动
     82     }
     83     *q = e;                             //插入新元素e
     84     L.lenght +=1;
     85     return OK;
     86 }   
     87 
     88 //删除第i位置元素,并用e返回其值
     89 Status ListDelete_sq(SqList &L, int i, ElemType &e){
     90     int *p,*q;
     91     if(i < 0 || i > L.lenght){
     92         return ERROR;  //i的值不合法
     93     }
     94     q = &L.elem[i];    //被删除元素的位置为i;
     95     e = *q;            //被删除元素的值赋值给e
     96     //被删除元素后的元素左移
     97     for (p = q; p< (L.elem + L.lenght); p++){  
     98         *p = *(p + 1);
     99     }
    100     --L.lenght;
    101     return OK;
    102 }  
    103 
    104 //得到第i个元素
    105 Status GetElem(SqList &L, int i, ElemType &e){
    106     ElemType *p;
    107     p = L.elem;
    108     int j = 1;
    109     if(i < 1){
    110         exit(OVERFLOW);//下表不合法
    111     }
    112     while(p && j < i){
    113         p = &L.elem[j];
    114         j++; //寻找第i个元素,同时检查p是否越界
    115     }
    116     if(!p || j > i){
    117         return false;//下标越界
    118     }
    119     e = L.elem[j-1];
    120     return OK;
    121 }
    122 
    123 //打印线性表
    124 void PrintList(SqList L){
    125     for(int i = 0; i < L.lenght; i++) {
    126         printf("%d ", *(L.elem + i));
    127     }
    128     printf("
    ");
    129 } 
    130 
    131 //合并两个线性表
    132 void Combine(SqList La, SqList Lb, SqList &Lc){
    133     ElemType *pa, *pb, *pc;
    134     Lc.listsize =  La.lenght + Lb.lenght;
    135     InitList(Lc, Lc.listsize); //初始化LCpc = Lc.elem;
    136     Lc.lenght = Lc.listsize;
    137     pc = Lc.elem;
    138     pa = La.elem;
    139     pb = Lb.elem;
    140     //还没有循环完
    141     while (pa <= &La.elem[La.lenght -1] && pb <= &Lb.elem[Lb.lenght -1]){
    142         if (*pa <= *pb){
    143             *pc++ = *pa++;
    144         }else{
    145             *pc++ = *pb++;
    146         }
    147     }
    148     //插入La的剩余元素  
    149     while(pa <= &La.elem[La.lenght -1]){
    150         *pc++ = *pa++;
    151     }
    152     //插入Lb的剩余元素 
    153     while(pb <= &Lb.elem[Lb.lenght -1]){
    154         *pc++ = *pb++;
    155     }
    156 } 
    157 
    158 //冒泡排序法,排序线性表
    159 void Sort(SqList &L){
    160     ElemType *pd1,*pd2,nums,length = L.lenght;
    161     for(int num = 0; num < length - 1; num++){
    162         for(int num1 = num + 1 ;num1 < length; num1++){
    163             pd1 = &L.elem[num];
    164             pd2 = &L.elem[num1];
    165             if(*pd1 > *pd2){
    166                 nums = *pd1;
    167                 *pd1 = *pd2;
    168                 *pd2 = nums;
    169             }
    170         }
    171     }
    172 }
    173  
    174 /*************************链式实现***************************/
    175 //单链表初始化
    176 Status InitList_L(LinkList &L){
    177     L = (LinkList)malloc(sizeof(LNode));
    178     if(!L){
    179         exit(OVERFLOW);  //分配存储空间失败
    180     }
    181     L->next = NULL; //初始的头结点为空
    182     return OK;
    183 }
    184 
    185 //逆向建立单链表
    186 Status CreateList_L(LinkList &L, int n){
    187     L = (LinkList)malloc(sizeof(LNode));
    188     if(!L){
    189         exit(OVERFLOW);  //分配存储空间失败
    190     }
    191     L->next = NULL; //初始的头结点为空
    192     printf("请输入5个整数:
    ");
    193     for(int i = n; i > 0; --i){
    194         LinkList p;
    195         p = (LinkList)malloc(sizeof(LNode));
    196         scanf("%d",&p->data);
    197         p->next = L->next;
    198         L->next = p;
    199     }
    200     return OK;
    201 }
    202 
    203 //在建立好的单链表中的第n个位置插入元素e
    204 Status ListInsert_L(LinkList &o, int n, ElemType e){
    205     LinkList L = o;
    206     int j = 0;//记录插入点的位置
    207     while(L && j < n - 1 && n > 0){
    208         L = L->next;
    209         j++;
    210     }
    211     if(L){//合法
    212         LinkList p;
    213         p = (LinkList)malloc(sizeof(LNode));
    214         p->data = e;
    215         p->next = L->next;
    216         L->next = p;
    217         return OK;
    218     }
    219 }
    220 
    221 //在建立好的单链表中的第n个位置删除元素,并用e返回
    222 Status ListDelete_L(LinkList &o, int n, ElemType e){
    223     LinkList L = o;
    224     int j = 0; //记录插入点的位置
    225     while(L && j < n - 1 && n > 0){
    226         L = L->next;
    227         j++;
    228     }
    229     if(L && L->next){//合法
    230         LinkList q;
    231         q = L->next;
    232         e = q->data;
    233         L->next = q->next;
    234         free(q);
    235         return OK;
    236     }
    237 }
    238 
    239 //合并链式线性表
    240 void Combine_L(LinkList &La, LinkList &Lb,LinkList &Lc){
    241     LinkList pa,pb,pc;
    242     pa = La->next;
    243     pb = Lb->next;
    244     //Lc = La;//把La作为Lc的头结点
    245     pc = Lc;
    246     while(pa && pb){
    247         if(pa->data <= pb->data){//判断两者得大小
    248             pc->next = pa;
    249             pa = pa->next; //pa指针下移
    250         }else{
    251             pc->next = pb;
    252             pb = pb->next; //pb指针下移
    253         }
    254         pc = pc->next; //pc下移一位
    255     }
    256     pc->next = pa ? pa : pb;
    257     free(La);
    258     free(Lb);
    259 }
    260 
    261 //得到第i个元素
    262 Status GetElem_L(LinkList &L, int i, ElemType &e){
    263     LinkList p;
    264     p = L;
    265     int j = 0;
    266     if(i < 1){
    267         exit(OVERFLOW);//下表不合法
    268     }
    269     while(p && j < i){
    270         p = p->next;//寻找第i个元素,同时检查p是否越界
    271         j++;
    272     }
    273     if(!p || j > i){
    274         return false;//下标越界
    275     }
    276     e = p->data;
    277     return OK;
    278 }
    279 
    280 //冒泡排序法排序单链表
    281 void Sort_L(LinkList &L){
    282     LinkList p,q;
    283     int num;
    284     for(p = L; p != NULL; p = p->next){
    285         for(q = p->next;q != NULL; q = q->next){
    286             if(p->data > q->data){
    287                 num = p->data;
    288                 p->data = q->data;
    289                 q->data = num;
    290             }
    291         }
    292     }
    293 }
    294 
    295 //打印链表节点信息
    296 void PrintfList_L(LinkList L){
    297     if(L){
    298         do{
    299             L = L->next;
    300             printf("%d ",L->data);
    301         }while(L->next);
    302     }
    303     printf("
    ");
    304 }
    305 
    306 /***********************双向链表实现*************************/
    307 //单链表初始化
    308 Status InitList_Du(DuLinkList &L){
    309     L = (DuLinkList)malloc(sizeof(DulNode));
    310     if(!L){
    311         exit(OVERFLOW);  //分配存储空间失败
    312     }
    313     L->next = NULL; //初始的头结点为空
    314     L->prior = NULL;
    315     return OK;
    316 }
    317 
    318 //在双向链表中第n个位置插入元素e;
    319 Status ListInsert_Dul(DuLinkList &P, int n, ElemType e){
    320     DuLinkList L = P;
    321     int j = 0;//记录插入点的位置
    322     while(L && j < n - 1 && n > 0){
    323         L = L->next;
    324         j++;
    325     }
    326     if(L){//合法
    327         DuLinkList c;
    328         c = (DuLinkList)malloc(sizeof(DulNode));
    330         c->data = e;
    331         c->next = L->next;
    332         L->next = c;
    333         if(c->next){
    334             c->next->prior = c;
    335         }
    336         c->prior = L;
    337         return OK;
    338     }
    339 }
    340 
    341 //在双向链表中第n个位置删除元素,并用e返回数据;
    342 Status ListDelete_Dul(DuLinkList &P, int n, ElemType &e){
    343     DuLinkList L = P;
    344     int j = 0;//记录插入点的位置
    345     while(L && j < n && n > 0){
    346         L = L->next;
    347         j++;
    348     }
    349     if(L){//合法
    350         e = L->data;
    351         L->prior->next = L->next;
    352         L->next->prior = L->prior;
    353         //free(L);
    354         return OK;
    355     }
    356 }
    357 
    358 //打印双向链表的数据
    359 void PrintList_Du(DuLinkList L){
    360     if(L){
    361         do{
    362             L = L->next;
    363             printf("%d ",L->data);
    364         }while(L->next);
    365     }
    366     printf("
    ");
    367 }
    368 
    369 //主方法
    370 void main(){
    371     ElemType e,f;
    372     int init,i,elem;    
    373     int TestData[8] = {9,1,8,5,7,2,1,3};
    374     int TestDataTwo[5] = {8,3,2,6,1};
    375     
    376     printf("*************线性表顺序实现*************
    ");
    377     SqList La,Lb,Lc;
    378     init = InitList(La, LIST_INIT_SIZE);
    379     
    380     for (i = 0; i < 8; i++) {//初始化La
    381         ListInse_Sq(La, TestData[i], i);
    382     }
    383     printf("La:
    构造后的La:");
    384     PrintList(La);
    385     
    386     GetElem(La,3,e);//得到第3个元素
    387     printf("得到La的第3个元素是:%d
    ",e);
    388 
    389     ListDelete_sq(La,3,e);//线性表的删除操作
    390     printf("删除后的La:");
    391     PrintList(La);
    392 
    393     ListInse_Sq(La,e,3);//还原数据
    394   
    395     Sort(La);//排序  
    396     printf("排序后的La:");
    397     PrintList(La);
    398 
    399     printf("Lb:
    构造后的Lb:");
    400     InitList(Lb, LIST_INIT_SIZE);
    401     for (i = 0; i < 5; i++) {  
    402         ListInse_Sq(Lb, TestDataTwo[i], i);
    403     }
    404     PrintList(Lb);
    405 
    406     Sort(Lb);//排序Lb
    407     printf("排序后的Lb:");
    408     PrintList(Lb);
    409 
    410     printf("合并La与Lb后的Lc:");//合并La,Lb
    411     Combine(La, Lb, Lc);
    412     PrintList(Lc);
    413 
    414     printf("
    *************线性表链式实现*************
    ");
    415     LinkList LaL,LbL,LcL,LdL;
    416     //CreateList_L(LbL,5)//逆序建立单链表
    417     InitList_L(LaL);//初始化单链表
    418     printf("LaL:
    构造后的LaL:");
    419     for (i = 1; i <= 8; i++) {//初始化La
    420         ListInsert_L(LaL, i, TestData[i-1]);
    421     }
    422 
    423     PrintfList_L(LaL);//打印单链表信息
    424 
    425     GetElem_L(LaL,3,e);//得到第3个元素
    426     printf("得到LaL的第3个元素是:%d
    ",e);
    427 
    428     ListInsert_L(LaL,3,10);//插入新元素
    429     printf("插入后的LaL:");
    430     PrintfList_L(LaL);
    431     
    432     ListDelete_L(LaL,3,e);//删除添加的新元素
    433     printf("删除后的LaL:");
    434     PrintfList_L(LaL);
    435 
    436     Sort_L(LaL);//排序  
    437     printf("排序后的LaL:");
    438     PrintfList_L(LaL);
    439     
    440     printf("LbL:
    构造后的LbL:");
    441     InitList_L(LbL);//初始化单链表
    442     
    443     for (i = 1; i < 6; i++) {  
    444         ListInsert_L(LbL, i, TestDataTwo[i-1]);
    445     }
    446     PrintfList_L(LbL);
    447     
    448     printf("排序后的LbL:");
    449     Sort_L(LbL);//排序  
    450     PrintfList_L(LbL);
    451 
    452     printf("合并La与Lb后的Lc:");
    453     InitList_L(LcL);//初始化单链表
    454     Combine_L(LaL, LbL, LcL);
    455     PrintfList_L(LcL);
    456 
    457     printf("
    *************双向链表的实现*************
    ");
    458     DuLinkList DuLa;
    459     //初始化双向链表
    460     InitList_Du(DuLa);
    461     
    462     for (i = 1; i < 9; i++) {
    463         ListInsert_Dul(DuLa, i, TestData[i-1]);
    464     }
    465     printf("DuLa:
    构造后的DuLa:");
    466     PrintList_Du(DuLa);
    467     printf("添加新元素元素后的DuLa:");
    468     ListInsert_Dul(DuLa, 3, 10); //在第三个位置添加元素10
    469     PrintList_Du(DuLa);
    470 
    471     printf("删除新添加元素后的DuLa:");
    472     ListDelete_Dul(DuLa,3,e);//删除元素
    473     PrintList_Du(DuLa);
    474 
    475 }

     运行结果:

    需要补充一下知识点:C语言动态内存分配,C动态内存分配主要有这几个函数:malloc、free、calloc、realloc

    malloc:原型 void *malloc(unsigned size)

    size表示分配内存的大小,函数会从内存池里取一块连续的内存,返回指向内存起始位置的指针,这块内存进行初始化,需要手动初始化也可以通过calloc初始化。

    注意:malloc分配的是连续的内存。可用内存小于请求,malloc向操作系统请求得到更多的内存,如果无法提供更多内存,则返回一个NULL指针。

    例如:初始化线性表(构造空的线性表 )
    L.elem = (ElemType *)malloc(lenght * sizeof(ElemType));

    calloc:原型 void*calloc(unsigned n,unsigned size)

    其中n表示需要分配内存的数据项个数,size指每个数据项的大小。malloc和calloc之间主要区别:calloc返回指向内存的指针之前把它初始化未0。 请求内存数量的方式不同。

    realloc:原型:void *realloc(void*list,unsigned size)

    将list所指的已分配内存区的大小改为size。realloc是修改一个原先已经分配的内存块的大小。如果原先的内存块无法改变大小,realloc将分配另一块正确大小的内存,并把原先那块内存的内容复制到新的快上。

    例如:ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize +LISTINCREMENT)*sizeof(ElemType));  
    free():  原型:void free (void* list);
      C语言中,free可以释放calloc, malloc, realloc动态分配的空间,注意:释放的不是自己定义的指针,而是定义的指针指向的空间。自己定义的普通指针能不能可以通过free
    释放,这个要看情况。如果定义的指针指向动态分配的地址空间,则可以使用free释放指针指向的这段空间;否则,就不能使用free释放指针指向的空间。

  • 相关阅读:
    PNG文件格式具体解释
    opencv2对读书笔记——使用均值漂移算法查找物体
    Jackson的Json转换
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 单词接龙
  • 原文地址:https://www.cnblogs.com/zyf-zhaoyafei/p/4580517.html
Copyright © 2020-2023  润新知