zoukankan      html  css  js  c++  java
  • 【转】基础知识系列2--线性表之链表

    原文地址:http://www.cnblogs.com/mcgrady/p/3209419.html

    上一篇我们总结完了顺序表,这一篇我们要总结的是线性表的链表,我想从以下几点进行总结。

    1,为什么要使用链表? 
    2,链表的存储结构? 
    3,链表的常用操作代码实现?

    1.为什么要使用链表

    通过上一篇的学习,我们知道顺序表存在一些问题,主要有以下两个方面。

    1,顺序表的长度是固定的,如果超出分配的长度就会造成溢出,如果存放的数据太少则会造成空间浪费。 
    2,在插入元素和删除元素时(尤其不在尾部时),会移动大量的元素,造成性能和效率低下。

    基于以上问题,使用链表可以很好地避免顺序表中出现的问题。这也是我们要使用链表的原因。

    2.链表的存储结构

    ds06

    从上图可以看出,单链表中的每个结点都包含一个“数据域”和一个“指针域”。“数据域”中包含当前结点的数据,“指针域”包含下一节点的存储地址,头指针head是指向开始结点的,结束结点没有后继结点,所以结束结点的指针域为空,即null。

    3.链表的常用操作及实现代码

    链表常用的操作有:

    1,插入结点到表头

    思路:将head头指针的next指针给新增结点的next,然后将整个新增结点给head头指针的next。因此时间复杂度为O(1)。

    示意图:

    ds007 
    2,插入结点到表尾

    思路:插入方法与插入到表头一样,只不过多一个步骤就是通过head头指针循环找到终端结点。因此时间复杂度为O(n)。

    示意图:

    ds07 
    3,插入结点(1≤i≤ListLength(L))

    思路:插入方法与插入到表头一样,多循环查找当前结点的动作。因此时间复杂度为O(n)。

    示意图:

    ds08 
    4,删除结点

    思路:同插入结点一样,时间复杂度为O(n)。

    示意图:

    ds09 
    5,查找结点

    思路:与插入结点和删除结点方法类似,时间复杂度为O(n)。 
    6,获取链表长度

    思路:不像顺序表是连续存储的,获取表的长度非常容易。在链表中,数据不是连续存储的,因此需要循环遍历才能求得链表的长度,所以时间复杂度为O(n)。

    代码实现:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #define OK     0
      5 #define ERROR -1
      6 
      7 typedef int Status;  //函数结果状态
      8 typedef int ElemType; 
      9 typedef struct Node
     10 {
     11     ElemType data;
     12     struct Node *next;
     13 }Node;
     14 typedef struct Node *ChainList;
     15 Node *p;
     16 ChainList head;
     17 
     18 Status Init(ChainList *head)
     19 {
     20     *head = (ChainList)malloc(sizeof(Node));
     21 
     22     if(*head == NULL)
     23         return ERROR;
     24 
     25     (*head)->next = NULL;
     26     
     27     return OK;
     28 }
     29 //由于第i个结点的存储地址是存储在第i-1个结点的next中,因此,先让指针指向第i-1个结点,然后生成一个新结点插入
     30 Status Insert(ChainList head,int i,ElemType e)
     31 {
     32     int j=0;
     33     ChainList p,s;
     34     
     35     p = head;
     36     while(p!=NULL&&j<i-1)  //head内不保存数据
     37     {
     38         p = p->next;
     39         j++;
     40     }
     41 
     42     if(p==NULL||j>i-1)    //这个j>i-1代表着i不能输入小于1的非法值
     43         return ERROR;
     44 
     45     s = (ChainList)malloc(sizeof(Node));
     46     s->data = e;
     47     s->next = p->next;
     48     p->next = s;
     49     
     50     return OK;
     51 }
     52 
     53 Status Delete(ChainList head,int i)
     54 {
     55     int j=0;
     56     ElemType e;
     57     ChainList p,s;
     58     p=head;
     59 
     60     while(p!=NULL&&j<i-1)
     61     {
     62         p = p->next;
     63         j++;
     64     }
     65 
     66     if(p==NULL)
     67         return ERROR;
     68     else
     69     {
     70         s=p->next;
     71         p->next = s->next;
     72         e = s->data;
     73         free(s);
     74         return OK;
     75     }
     76 }
     77 
     78 int GetLength(ChainList head)
     79 {
     80     int i=0;
     81     ChainList p = head->next;
     82     
     83     while(p!=NULL)
     84     {
     85         p = p->next;
     86         i++;
     87     }
     88 
     89     return i;
     90 }
     91 
     92 Status GetDataByIndex(ChainList head,int i,ElemType *e)
     93 {
     94     int j=0;
     95     ChainList p,s;
     96 
     97     p=head->next;
     98 
     99     while(p!=NULL&&j<i-1)
    100     {
    101         p=p->next;
    102         j++;
    103     }
    104 
    105     if(p==NULL||j>i-1)
    106         return ERROR;
    107     *e = p->data;
    108 
    109     return OK;
    110 }
    111 
    112 Status Display(ChainList head)
    113 {
    114     ChainList p=head->next;
    115     printf("链表:");
    116     while(p!=NULL)
    117     {
    118         printf("%d ",p->data);
    119         p=p->next;
    120     }
    121     printf("
    ");
    122 
    123     return OK;
    124 }
    125 
    126 int main(void)
    127 {
    128     ChainList head;
    129     ElemType e;
    130     int j,k;
    131 
    132     printf("初始化
    ");
    133     if(Init(&head) == -1)
    134         printf("Init Error
    ");
    135     printf("初始化后,链表长度:%d
    ",GetLength(head));
    136 
    137     printf("插入10条数据
    ");
    138     srand((unsigned)time(NULL));
    139     for(j=0;j<10;j++)
    140     {
    141         if(Insert(head,1,j) == -1)
    142             printf("Insert Error
    ");
    143     }
    144     Display(head);
    145 
    146     printf("删除第3条数据
    ");
    147     if(Delete(head,3) == -1)
    148         printf("Delete Error
    ");
    149     printf("删除成功
    ");
    150     Display(head);
    151 
    152     printf("获取第5个结点的数据
    ");
    153     if(GetDataByIndex(head,5,&e) == -1)
    154         printf("GetData Error
    ");
    155     printf("%d
    ",e);
    156 
    157     return 0;
    158 }

    运行结果

  • 相关阅读:
    最长公共前缀
    罗马数字转整数
    回文数
    整数反转
    Linux内核设计与实现——进程管理
    技术派-常用的一些VS相关的宏名
    假如面试3道小学数学题,你可否会?
    技术派-不用sqrt手工计算平方根
    观察者-学历差距造成的差距有多大
    10G文件如何对里面单词出现排序
  • 原文地址:https://www.cnblogs.com/losing-1216/p/4962527.html
Copyright © 2011-2022 走看看