• 线性表的链式存储


          线性表的链式存储。主要是单链表的相关知识,介绍了正序建立单链表、逆序建立单链表、单链表的插入、删除、查找、输出以及单链表的合并方法。单链表的合并前提是两个都有序。具体知识点详见代码注释。

      1 /***
      2 线性表的链式存储结构不能随机存储,整个链表的存取都必须从头结点开始。但是没有顺序存储的缺点:插入或者删除时需要移动大量元素
      3 其特点是用一组任意的存储空间存储线性表的数据元素
      4 
      5 结点:数据域和指针域
      6 */
      7 #include<stdio.h>
      8 #include<stdlib.h>
      9 #define MAX 100000
     10 //**********************线性表的单链表存储结构***********************
     11 typedef struct LNode
     12 {
     13     int data;            //数据域
     14     struct LNode *next;  //指针域
     15 } LNode,*LinkList;       //LinkList是LNode型结构的指针
     16 
     17 
     18 //**************************头插法逆序建立单链表****************************
     19 void CreateList_L1(LinkList &L,int n)
     20 {
     21     //逆位序输入n个元素值,建立带有头结点的单链表,时间复杂度为O(n)
     22     L->next = NULL;//先建立个带有头结点的单链表L,使头结点指针域为空,
     23     for (int i = n; i > 0; --i)
     24     {
     25         LinkList p = (LinkList)malloc(sizeof(LNode));//生成新结点
     26         scanf("%d",&p->data);
     27         //插入到表头
     28         p->next = L->next;
     29         L->next = p;
     30     }
     31 
     32 }
     33 
     34 //**************************尾插法正序建立单链表****************************
     35 void CreateList_L2(LinkList &L,int n)
     36 {
     37     //借助一个中间变量,正序建立n个元素的单链表,时间复杂度仍然为O(n)
     38     //先建立个带有头结点的单链表L,头结点指针域为空,默认使用Linklist建立L是即为空
     39     LinkList r = L;
     40     for (int i = 0; i < n; ++i)
     41     {
     42         LinkList p = (LinkList)malloc(sizeof(LNode));//生成新结点
     43         scanf("%d",&p->data);
     44         //插入到表尾
     45         r->next = p;
     46         r = p;
     47     }
     48     r->next = NULL;
     49 }
     50 
     51 //**************************按序输出单链表的各个元素****************************
     52 void PrintList_L(LinkList L)
     53 {
     54     LinkList p = L->next;//p指向第一个元素
     55     while(p)
     56     {
     57         printf("%d ", p->data);
     58         p = p->next;
     59     }
     60 }
     61 
     62 //***********************取出指定位序的单链表中的数据元素***********************
     63 int  GetElem_L(LinkList L,int i)
     64 {
     65     //时间复杂度为O(n)
     66     //L为带头结点的单链表的头指针
     67     //返回链表的第i个元素,若没有,则错误提示
     68     LNode *p = L->next; //初始化,p指向第一个结点
     69     int j = 1;//计数器
     70     int e;//返回值
     71     while(p && j<i)
     72     {
     73         //顺指针向后查找,知道p指向第i个元素或者p为空
     74         p = p->next;
     75         ++j;
     76     }
     77     if (!p || j>i)
     78     {
     79         printf("没有找到该元素,请确认后重新输入位序!
    ");
     80         e = MAX;
     81         return e;
     82     }
     83     e = p->data;
     84     return e;
     85 }
     86 
     87 
     88 //*******************向单链表的指定位序插入一个元素********************
     89 void ListInsert_L(LinkList &L,int i,int e)
     90 {
     91     //在带头结点的单链表L的第i个位置之前插入元素e,1=<i<=length(L)+1,时间复杂度为O(n)
     92     /*
     93     LNode *p = L->next; //初始化,p指向第一个结点,下面一句话效果一样,因为LinkList是指向LNode型的指针变量,无需再加*号
     94     LinkList p = L->next;
     95     int j = 1;//计数器
     96     */
     97     //上面使p指向第一个结点的方法有问题,如果要将元素插在第一位会有bug,故要从头结点开始
     98     LinkList p = L;
     99     int j = 0;
    100     while(p && j<i-1)
    101     {
    102         p = p->next; //寻找第i-1个结点,使p指向它
    103         ++j;
    104     }
    105     if (!p || j>i-1)
    106     {
    107         printf("要插入的位置没有找到,可能是插入位序有误!
    ");
    108         getchar();
    109         exit(1);
    110     }
    111     LinkList s = (LinkList)malloc(sizeof(LNode));//生成一个结点s
    112     s->data = e;
    113     //插入结点
    114     s->next = p->next;
    115     p->next = s;
    116 }
    117 
    118 //********************删除单链表的指定位序的一个元素********************
    119 void ListDelete_L(LinkList &L,int i)
    120 {
    121     //时间复杂度为O(n)
    122     //在带头结点的单链表L中,删除第i个位置的元素.i<=length(L)
    123     LNode *p = L; //初始化,p指向头结点
    124     int j = 0;//计数器
    125     while(p->next && j<i-1)
    126     {
    127         p = p->next; //使p指向被删除结点的前一个结点,即p指向i-1
    128         ++j;
    129     }
    130     if (!(p->next) || j>i-1)
    131     {
    132         //要保证p的后一个元素有值,即被删除元素存在
    133         printf("删除位置不合理,请重新确认!
    ");
    134         getchar();
    135         exit(1);
    136     }
    137     //删除该元素
    138     LNode *q = p->next;
    139     p->next = q->next;
    140     free(q);//释放结点
    141 }
    142 
    143 //**************************有序链表的合并******************************
    144 void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc)
    145 {
    146     //已知单链线性表La和Lb的元素按值非递减排序
    147     //归并La和Lb得到新的单链表Lc,Lc的元素也按值非递减排列
    148     LinkList pa,pb,pc;
    149     pa = La->next;
    150     pb = Lb->next;
    151     //用La的头结点作为Lc的头结点
    152     pc = La;
    153     Lc = pc;
    154     while(pa && pb)
    155     {
    156         if (pa->data <= pb->data)
    157         {
    158             pc->next = pa;
    159             pc = pa;
    160             pa = pa->next;
    161         }
    162         else
    163         {
    164             pc->next = pb;
    165             pc = pb;
    166             pb = pb->next;
    167         }
    168     }
    169     pc->next = pa?pa:pb;
    170     free(Lb);//释放Lb的头结点
    171 }
    172 
    173 int main()
    174 {
    175     //定义3个链表,初始化3个头结点
    176     LinkList la = (LinkList)malloc(sizeof(LNode));
    177     LinkList lb = (LinkList)malloc(sizeof(LNode));
    178     LinkList lc;//
    179     int count;//计数使用,链表初始化时记录链表元素个数
    180     int location,value;//插入时的位置和值
    181     char c;
    182     //使用头插法逆序建立链表
    183     printf("请输入la链表元素个数:");
    184     scanf("%d",&count);
    185     CreateList_L1(la,count);
    186     printf("逆序建立的la链表元素为:");
    187     PrintList_L(la);
    188 
    189     //使用尾插法正序建立链表
    190     printf("
    
    请输入链表lb元素个数:");
    191     scanf("%d",&count);
    192     CreateList_L2(lb,count);
    193     printf("正序建立的lb链表元素为:");
    194     PrintList_L(lb);
    195 
    196     //向正序建立的单链表中插入数据
    197     printf("
    
    请输入lb插入位置和插入值:");
    198     scanf("%d%d",&location,&value);
    199     ListInsert_L(lb,location,value);
    200     printf("插入元素之后的链表元素为:");
    201     PrintList_L(lb);
    202 
    203     //继续测试该链表的删除效果
    204     printf("
    
    请输入lb删除位置:");
    205     scanf("%d",&location);
    206     ListDelete_L(lb,location);
    207     printf("删除元素之后的链表元素为:");
    208     PrintList_L(lb);
    209 
    210     //测试GetElem函数是否有效
    211     printf("
    
    请输入需要得到的元素位置:");
    212     scanf("%d",&location);
    213     value = GetElem_L(lb,location);
    214     if (value == MAX)
    215     {
    216         printf("输入错误或者没有该位置的元素!
    ");      
    217     }else
    218     {
    219         printf("该元素的值为:%d",value);
    220     }
    221 
    222     //测试两个链表的归并,前提是两个链表都有序
    223     MergeList_L(la,lb,lc);
    224     printf("
    
    两个链表合并后lc的元素是:");
    225     PrintList_L(lc);
    226 
    227     return 0;
    228 }
  • 相关阅读:
    .Net常见笔试题
    冒泡排序算法 C#版
    Bundle捆绑压缩技术
    异步Ajax
    HtmlHelper总结
    HtmlHelper的扩展分页方法
    WCF
    程序猿值得看的几个技术网站(记录)
    Struts2和SpringMVC的区别
    nginx配置文件作用介绍
  • 原文地址:https://www.cnblogs.com/wujiyang/p/4335237.html
Copyright © 2020-2023  润新知