zoukankan      html  css  js  c++  java
  • 第二章 线性表

    1. 线性表:n个数据元素的有序集合。

    线性表是一种常用的数据结构。在实际应用中,线性表都是以、队列、字符串数组等特殊线性表的形式来使用的。由于这些特殊线性表都具有各自的特性,因此,掌握这些特殊线性表的特性,对于数据运算的可靠性和提高操作效率都是至关重要的。  线性表是一个线性结构,它是一个含有n≥0个结点的有限序列,对于其中的结点,有且仅有一个开始结点没有前驱但有一个后继结点,有且仅有一个终端结点没有后继但有一个前驱结点,其它的结点都有且仅有一个前驱和一个后继结点。

    特征:

    1.集合中必存在唯一的一个“第一元素”;
    2.集合中必存在唯一的一个 “最后元素” ;
    3.除最后一个元素之外,均有 唯一的后继(后件);
    4.除第一个元素之外,均有 唯一的前驱(前件)。

    java中的List接口,就是线性表。ArrayList就是顺序线性表,LinkedList就是链表线性表。

    2. 线性表的顺序表示:ArrayList

    一般使用数组(C语言中的数组采用顺序存储方式。即连续地址存储)来描述。

    优点:在于随机访问元素,

    缺点:插入和和删除的时候,需要移动大量的元素。

    c语言实现代码:

    // Test.cpp : Defines the entry point for the console application.  
    //  
      
    #include "stdafx.h"  
    #include <stdio.h>  
    #include "stdlib.h"  
    //宏定义  
    #define TRUE   1  
    #define FALSE   0  
    #define OK    1  
    #define ERROR   0  
    #define INFEASIBLE -1  
    #define OVERFLOW -2  
      
    #define LT(a,b)   ((a)<(b))  
    #define N = 100         
      
    #define LIST_INIT_SIZE 100 //线性表初始空间分配量  
    #define LISTINCREMENT   10 //线性表空间分配的增量  
      
    typedef int Status;  
    typedef int ElemType;  
      
    typedef struct LNode{  
        ElemType  *elem;        //存储空间的基地址  
        int      lenght;        //当前的长度  
        int      listsize;      //当前分配的存储容量  
    }SqList;  
      
    /** 
     *构造空的线性表 
     */  
      
    Status initList(SqList &L, int lenght){  
        if (lenght == 0) lenght = LIST_INIT_SIZE;  
        L.elem = (ElemType *)malloc(lenght * sizeof(ElemType));  
        if(!L.elem) exit(OVERFLOW);  //分配存储空间失败  
        L.lenght = 0;                //初始空表长度为0  
        L.listsize = lenght ;//初始存储容量为100  
        return OK;  
    }  
    /************************************************************************/  
    /* 在第i位置插入e 
    */  
    /************************************************************************/  
    Status insertList(SqList &L, ElemType e, int i){  
        ElemType *p,  *q;  
        if(i<0 ||i > L.lenght) return ERROR;  //i值不合法  
        if (L.lenght >= L.listsize) {  
            ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize +LISTINCREMENT)*sizeof(ElemType));  
            if(!newbase) return OVERFLOW;   //存储分配失败    
            L.elem = newbase;               //新基值  
            L.listsize += LISTINCREMENT;    //增加存储容量  
        }  
        q = &L.elem[i];                     //q为插入的位置  
        for (p = &L.elem[L.lenght]; p>=q; --p) {  
            *p = *(p-1);                    //i元素之后的元素往后移动  
        }  
        *q = e;                             //插入e  
        L.lenght +=1;  
        return OK;  
      
    }  
    /************************************************************************/  
    /* 快速排序  
    */  
    /************************************************************************/  
    void sortList(SqList &L){  
          
      
    }  
    /************************************************************************/  
    /* 删除第i位置元素,并用e返回其值                                                                     */  
    /************************************************************************/  
    Status deleteListElem(SqList &L, int i, ElemType &e){  
        int *p,  *q;  
        if(i<0 ||i > L.lenght) return ERROR;  //i值不合法  
        q = &L.elem[i];                       //被删除元素的位置为i,L.elem就是数组名,  
        e = *q;                               //被删除元素的值赋值给e  
        for (p = q; p< (L.elem + L.lenght); p++){ //元素左移  
            *p = *(p+1);  
        }  
        --L.lenght;  
        return OK;  
    }  
      
    /************************************************************************/  
    /*  快速排序 
    */  
    /************************************************************************/  
      
    int partition(SqList &L, ElemType low, ElemType high){  
        ElemType pivotkey = L.elem[low];               //枢轴记录关键字  
        while (low < high) {                  //从表的两端向中间扫描  
            while (low < high &&  L.elem[high] >= pivotkey ) --high;//高端位置扫描  
            L.elem[low] = L.elem[high];     //交换数据,小于pivotkey移到低端  
            L.elem[high] = pivotkey;  
      
            while (low < high && L.elem[low] <= pivotkey ) ++low;     //低端扫描  
            L.elem[high] = L.elem[low];               //交换数据 大于pivotkey移到高端  
            L.elem[low] = pivotkey;                                   
        }  
        return low;  
    }  
      
    void quickSort(SqList &L, ElemType low, ElemType high){  
        int pivot;  
        if(low < high) {                                          
            pivot =  partition(L,  low,  high);       
            quickSort(L,  low,  pivot -1);          //低端子表排序  
            quickSort(L,  pivot +1, high);          //高端子表排序  
        }  
          
    }  
      
      
    /************************************************************************/  
    /*  
    合并两个线性表 
    */  
    /************************************************************************/  
      
    void mergeList(SqList La, SqList Lb,  SqList &Lc){  
        ElemType *pa, *pb, *pc;  
        Lc.listsize =  La.lenght + Lb.lenght;  
        initList(Lc, Lc.listsize);          //初始化LCpc = Lc.elem;  
        Lc.lenght = Lc.listsize;  
        pc = Lc.elem;  
        pa = La.elem;  
        pb = Lb.elem;  
        while (pa <= &La.elem[La.lenght -1] && pb <= &Lb.elem[Lb.lenght -1]){  
            if (*pa <= *pb) *pc++ = *pa++;  
            else *pc++ = *pb++;  
        }  
        while(pa <= &La.elem[La.lenght -1]) *pc++ = *pa++; //插入La的剩余元素  
        while(pb <= &Lb.elem[Lb.lenght -1]) *pc++ = *pb++; //插入Lb的剩余元素  
      
    }  
      
    /************************************************************************/  
    /* 打印list 
    */  
    /************************************************************************/  
    void printList(SqList L){  
        printf("当前值:");   
        for (int i =0; i<L.lenght;i++) {  
            printf("%d ", *(L.elem+i)); // L.elem为首地址  
        }   
        printf("
    ");   
    }  
      
    void main()  
    {  
        SqList La,Lb,Lc;  
        ElemType e;  
        int init,i;  
        init = initList(La, LIST_INIT_SIZE);  
        int data[6] = {5,3,6,2,7,4};  
        for (i=0; i<6;i++) {  
            insertList(La,  data[i],  i);  
        }  
        printf("LA:
    ");   
        printList(La);  
        deleteListElem(La, 3, e );  
        printList(La);  
        insertList(La,  e,  3);  
        printList(La);  
      
        //排序  
        quickSort(La,0, La.lenght-1);  
        printList(La);  
      
        printf("LB:
    ");   
        initList(Lb, LIST_INIT_SIZE);  
        int Bdata[5] = {1,3,2,4,6};  
        for (i=0; i<5;i++) {  
            insertList(Lb,  Bdata[i],  i);  
        }  
        //排序  
        quickSort(Lb,0, Lb.lenght-1);  
        printList(Lb);  
      
        mergeList(La, Lb,  Lc);  
        printList(Lc);  
      
    }  

    3. 线性表的链表表示LinkedList

    一般使用链表来描述。

    优点:对于新增和删除操作add和remove和方便。不需要移动元素。

    缺点:不方便随机访问元素,LinkedList要移动指针

    代码实现:

      1 // Test.cpp : Defines the entry point for the console application.  
      2 //  
      3 #include "stdafx.h"  
      4 #include <stdio.h>  
      5 #include "stdlib.h"  
      6 //宏定义  
      7 #define TRUE   1  
      8 #define FALSE   0  
      9 #define OK    1  
     10 #define ERROR   0  
     11 #define INFEASIBLE -1  
     12 #define OVERFLOW -2  
     13   
     14 #define LT(a,b)   ((a)<(b))  
     15 #define N = 100         
     16   
     17 typedef int Status;  
     18 typedef int ElemType;  
     19   
     20 typedef struct LNode{  
     21     ElemType  data;               
     22     struct LNode   *next;     
     23 }LNode, *LinkList;  
     24   
     25 /************************************************************************/  
     26 /* 
     27 初始化链表 
     28 */  
     29 /************************************************************************/  
     30 Status initList(LinkList &L){  
     31     /*单链表的初始化*/  
     32     L = (LinkList)malloc(sizeof(LNode));    //申请一个头节点  
     33     if(!L) exit(OVERFLOW);          //申请空间失败    
     34     L->next=NULL;                //建立一个带都节点的空链表  
     35     return OK;  
     36   
     37     /*  
     38     需要改变指针的指针,所以参数必须是引用或者是 *L: 
     39     (*L) = (Lnode *)malloc(sizeof(Lnode)); 
     40     (*L)->next=NULL; 
     41     return 1;                                                                      
     42     */  
     43   
     44 }  
     45   
     46 /************************************************************************/  
     47 /*      
     48 创建链表 
     49 */  
     50 /************************************************************************/  
     51 void createList(LinkList L, int n){  
     52     /*单链表的初始化*/  
     53     if (!L) {  
     54         initList(L);  
     55     }  
     56     ElemType data;  
     57     LinkList p,q = L;  
     58     printf("输入节点数据的个数%d:
    ", n);  
     59     for(int i = 0; i<n; i++) {  
     60         p = (LinkList) malloc( sizeof(LNode)); //申请一个新节点  
     61         scanf("%d",&data);  
     62         p->data = data;  
     63         p->next = q->next;  
     64         q->next = p;  
     65         q = p;  
     66     }  
     67 }  
     68 /************************************************************************/  
     69 /* 在第i位置插入e 
     70 */  
     71 /************************************************************************/  
     72 Status insertList(LinkList L, ElemType e, int i){  
     73     LinkList s, p = L;  
     74     int j = 0;  
     75     while (p && j<i){                //寻找i节点  
     76         p = p->next;  
     77         j++;  
     78     }  
     79     if (!p ||j >i) return ERROR;  
     80     s = (LinkList) malloc(sizeof(LNode));       //生成新节点  
     81     s->data = e; s->next = p->next;            //插入L中  
     82     p->next = s;  
     83     return OK;  
     84   
     85 }  
     86   
     87 /************************************************************************/  
     88 /* 删除第i位置元素,并用e返回其值                                                                     */  
     89 /************************************************************************/  
     90 Status deleteListElem(LinkList L, int i, ElemType &e){  
     91     LinkList p, q;  
     92     int j = 0;  
     93     p = L;  
     94     while (p && j<i){  
     95         p = p->next;  
     96         ++j;  
     97     }  
     98     if (!p->next || j>i)  return ERROR;   //删除的位置不对  
     99     q  = p->next; p->next = q->next;  
    100     e = q->data; free(q);            //释放节点  
    101     return OK;  
    102 }  
    103   
    104   
    105 /************************************************************************/    
    106 /*  插入排序  
    107 */    
    108 /************************************************************************/    
    109   
    110 void  InsertSort(LinkList L)  
    111 {  
    112     LinkList  list;             /*为原链表剩下用于直接插入排序的节点头指针*/  
    113     LinkList  node;             /*插入节点*/  
    114     LinkList  p;          
    115     LinkList  q;          
    116   
    117     list = L->next;              /*原链表剩下用于直接插入排序的节点链表*/  
    118     L->next = NULL;              /*只含有一个节点的链表的有序链表。*/  
    119     while (list != NULL)   {    /*遍历剩下无序的链表*/  
    120         node = list, q = L;     
    121         while (q && node->data > q->data  ) {  
    122             p = q;  
    123             q = q->next;  
    124         }  
    125           
    126         if (q == L) {  /*插在第一个节点之前*/  
    127             L = node;  
    128         }  else {     /*p是q的前驱*/  
    129             p->next = node;     
    130         }  
    131         list = list->next;  
    132         node->next = q; /*完成插入动作*/  
    133   
    134     }  
    135 }  
    136   
    137   
    138   
    139 /************************************************************************/  
    140 /*  
    141 合并两个线性表 
    142 */  
    143 /************************************************************************/  
    144   
    145 void mergeList(LinkList  &La, LinkList  &Lb,  LinkList &Lc){  
    146     LinkList pa, pb, pc;  
    147     pa  = La->next;  
    148     pb  = Lb->next;  
    149     Lc =  pc = La;  
    150     while (pa && pa) {  
    151         if (pa->data > pb->data) {  
    152             pc->next = pb;  
    153             pc = pb;  
    154             pb =pb->next;  
    155         }else{  
    156             pc->next = pa;  
    157             pc = pa;   
    158             pa =pa->next;  
    159         }  
    160     }  
    161     pc->next = pa? pa :pb;  
    162     free(Lb);  
    163 }  
    164   
    165 /************************************************************************/  
    166 /* 打印list 
    167 */  
    168 /************************************************************************/  
    169 void printList(LinkList  L){  
    170     printf("当前值:");  
    171     LinkList p;  
    172     p = L->next;  
    173     while(p){  
    174         printf("%d ", p->data);   
    175         p = p->next;  
    176     }  
    177     printf("
    ");   
    178 }  
    179   
    180 void main()  
    181 {  
    182     LinkList  La,Lb,Lc;  
    183     ElemType e;  
    184     int init,i;  
    185     printf("LA:
    ");    
    186     initList(La);  
    187     createList(La, 5);  
    188     insertList(La, 7,  3);    
    189     printList(La);  
    190     deleteListElem(La, 3,  e);    
    191     printList(La);  
    192     InsertSort(La);  
    193     printList(La);  
    194   
    195     printf("Lb:
    ");    
    196     initList(Lb);  
    197     createList(Lb, 4);  
    198     InsertSort(Lb);  
    199     printList(Lb);  
    200   
    201     printf("Lc:
    ");   
    202     initList(Lc);  
    203     mergeList(La,   Lb,   Lc);  
    204     printList(Lc);  
    205   
    206 }  
  • 相关阅读:
    学习笔记之jq
    学习笔记之pytest
    本月学习小结(01/10
    本月学习小结(01/09
    学习笔记之Poetry
    学习笔记之Dynaconf
    学习笔记之asyncio — Asynchronous I/O
    Redis 根据key获取所有 HashKey
    Java ffmpeg 合成音视频文件
    Redis 存储中文方式
  • 原文地址:https://www.cnblogs.com/hust-chen/p/8039958.html
Copyright © 2011-2022 走看看