zoukankan      html  css  js  c++  java
  • 线性表学习笔记

      最近学习数据结构的线性表,主要是借助教材《数据结构》(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释放指针指向的空间。

  • 相关阅读:
    15道简单算法题
    提高SQL查询效率
    算法--两道百度笔试题
    .NET牛人应该知道些什么?
    VS创建、安装、调试 windows服务(windows service)
    Build System 和Test Framework overview总结
    3.8 Templates -- Actions
    3.7 Templates -- Links
    3.6 Templates -- Binding Element Class Names(绑定元素类名)
    3.5 Templates -- Binding Element Attributes(绑定元素属性)
  • 原文地址:https://www.cnblogs.com/zyf-zhaoyafei/p/4580517.html
Copyright © 2011-2022 走看看