zoukankan      html  css  js  c++  java
  • 数据结构-单链表-结构体定义

    单链表,用于存储逻辑关系为 "一对一" 的数据,与顺序表不同,链表不限制数据的物理存储状态,换句话说,使用链表存储的数据元素,其物理存储位置是随机的。

    结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。

    例如{1,2,3}:

      

    线性表的链式表示又称为非顺序映像或链式映像。

    各结点由两个域组成: 

      数据域:存储元素数值数据

      指针域:存储直接后继结点的存储位置  

        

    头指针是指向链表中第一个结点的指针

    首元结点是指链表中存储第一个数据元素a1的结点

    头结点是在链表的首元结点之前附设的一个结点;数据域内只放空表标志和表长等信息

    如何表示空表?

    答:有头结点时,当头结点的指针域为空时表示空表

    在链表中设置头结点有什么好处?

    答:⒈便于首元结点的处理

        首元结点的地址保存在头结点的指针域中,所以在链表的第一个位置上的操作和其它位置一致,无须进行特殊处理;

      ⒉便于空表和非空表的统一处理

        无论链表是否为空,头指针都是指向头结点的非空指针,因此空表和非空表的处理也就统一了。

    头结点的数据域内装的是什么?

    答:头结点的数据域可以为空,也可存放线性表长度等附加信息,但此结点不能计入链表长度值。

    链表(链式存储结构)的特点:

    1)结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻

    2)访问时只能通过头指针进入链表,并通过每个结点的指针域向后扫描其余结点,所以寻找第一个结点和最后一个结点所花费的时间不等

    这种存取元素的方法被称为顺序存取法

    链表的优缺点:

    优点:数据元素的个数可以自由扩充

       插入、删除等操作不必移动数据,只需修改链接指针,修改效率较高链表的优缺点

    缺点:存储密度小

       存取效率不高,必须采用顺序存取,即存取数据元素时,只能按链表的顺序进行访问(顺藤摸瓜)

    单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名

    若头指针名是L,则把链表称为表L

    用c++描述的单链表大致可以分两种,一种用结构体定义,一种用类定义;

    链表也可以分为头插法和尾插法

    头插法

    生成新结点
    将读入数据存放到新结点的数据域中
    将该新结点插入到链表的前端

      1 #include<iostream>
      2 using namespace std;
      3 
      4 typedef struct SingLinkList {
      5     int data;                  //数据域
      6     struct SingLinkList *next; //指针域
      7 }SLL,*Slist; //相当于struct SingLinkList,*Slist相当于struct SingLinkList *
      8 
      9 //新建链表,确认链表的长度
     10 void New_LinkList(Slist L,int n)  //Slist L相当于struct SingLinkList * L
     11 {
     12     int i;
     13     int v;
     14     Slist p;
     15     L->next = NULL;      
     16     
     17     //这是用前插法创建链表,此时就不需要使用尾结点了
     18     //所以遍历的结果是与输入值的顺序是相反的
     19     for (int i = n; i > 0; i--)
     20     {
     21         p = (Slist)malloc(sizeof(SLL));
     22         cin >> v;
     23         p->data = v;
     24         p->next = L->next;  //p的指针域指向L的指针域,即p指向空,
     25         L->next = p;        //但是此时只有p这个结点,还需要头结点指向p
     26                             //此时头结点指向p,而p指针域指向最后,
     27                       //可以认为p是尾结点,它的指针域自然要指向空了。
     28          //然后你需要几个结点就继续按照原来的一直干下去。记住这是前插法。
     29         //单链表的结点不像数组可以通过下标找到,它得从头开始找。
     30         //每个节点都与上一个结点相连没有名字是地址传地址
     31     }
     32 }
     33 
     34 // 获取链表中指定位置的数据元素
     35 int GetElem_LinkList( Slist L, int i, int *e)
     36 {
     37     Slist p;
     38     p = L->next;
     39     int j = 1;
     40 
     41     while (p && j < i)
     42     {
     43         p = p->next;
     44         ++j;
     45     }
     46 
     47     if (!p || j > i)
     48     {
     49         return 0;
     50     }
     51 
     52     *e = p->data;
     53     return 1;
     54 }
     55 
     56 // 在链表中指定位置插入数据
     57 int Isert_LinkList(Slist L, int i, int* e)
     58 {
     59     Slist p, s;
     60     p = L;
     61     int j = 0;
     62 
     63     while (p && j < i - 1)
     64     {
     65         p = p->next;
     66         ++j;
     67     }
     68 
     69     if (!p || j > i - 1)
     70     {
     71         return 0;
     72     }
     73 
     74     s = (Slist)malloc(sizeof(SLL));
     75     s->data = *e;
     76     s->next = p->next;
     77     p->next = s;
     78 
     79     return 1;
     80 }
     81 
     82 // 删除链表中指定数据元素
     83 int Delete_LinkList(Slist L, int i, int* e)
     84 {
     85     Slist p, q;
     86     p = L;
     87     int j = 0;
     88 
     89     while (p->next && j < i - 1)
     90     {
     91         p = p->next;
     92         ++j;
     93     }
     94 
     95     if (!(p->next) || j > i - 1)
     96     {
     97         return 0;
     98     }
     99 
    100 
    101     q = p->next;
    102     p->next = q->next;
    103     *e = q->data;
    104 
    105     free(q);
    106     return 1;
    107 }
    108 
    109 // 显示链表元素的内容
    110 int Print_LinkList(Slist L, char* s)
    111 {
    112     Slist p;
    113     
    114     p = L->next;
    115     if (p == NULL)
    116     {
    117         cout << "该链表为空!" << endl;
    118         return 0;
    119     }
    120 
    121     while (p != NULL)
    122     {
    123         cout << p->data << " ";
    124         p = p->next;
    125     }
    126     cout << endl;
    127     return 1;
    128 }
    129 
    130 int main()
    131 {
    132     // 创建并初始化链表
    133     SLL L;
    134     cout << "请输入五个节点的数据" << endl;
    135     New_LinkList(&L, 5);
    136     Print_LinkList(&L, (char*)"初始化链表:");
    137 
    138     int s, v;
    139 
    140     // 插入数据
    141     cout << "请输入数据插入的位置和值:";
    142     cin >> s >> v;
    143     Isert_LinkList(&L, s, &v);
    144     Print_LinkList(&L, (char*)"插入后的节点数:");
    145 
    146 
    147     // 查询数据
    148     cout << "请输入数据查询的位置:";
    149     cin >> s;
    150     GetElem_LinkList(&L, s, &v);
    151     cout << "" << s << "个数据是:" << v << endl;
    152 
    153     // 删除出数据
    154     cout << "请输入数据删除的位置:";
    155     cin >> s;
    156     if (Delete_LinkList(&L, s, &v))
    157     {
    158         cout << "数据删除成功,你所删除的数据是:" << v << endl;
    159     }
    160     else
    161     {
    162         cout << "数据删除失败!" << endl;
    163     }
    164     Print_LinkList(&L, (char*)"删除后的链表:");
    165 
    166 
    167     return 0;
    168 }

     尾插法

    从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针r指向链表的尾结点。
    初始时,r同L均指向头结点。每读入一个数据元素则申请一个新结点,将新结点插入到尾结点后,r指向新结点。

     

      1 #include <iostream>
      2 using namespace std;
      3 
      4 #define ERROR   0
      5 #define OK      1
      6 
      7 
      8 // 链表节点的结构体
      9 typedef struct LNode
     10 {
     11     int data;            // 数据域
     12     struct LNode* next;    // 指针域
     13 }SLL , * SLNode;
     14 
     15 
     16 // 新建链表,确认链表的长度
     17 void New_LinkList(SLNode L, int n)
     18 {
     19     int i;
     20     int v;
     21 
     22     SLNode p,r;        // 新建单链表
     23     L->next = NULL;
     24     r = L;          //尾指针r指向头节点
     25 
     26     //链表的尾插法
     27     for (int i = n; i > 0; i--)
     28     {
     29         p = (SLNode)malloc(sizeof(SLL));  //生成新结点
     30         cin >> v;
     31         p->data = v;                  //输入元素值
     32         p->next = NULL; r->next = p;  //插入到表尾
     33         r = p;                        //r指向新的尾结点
     34         //插入的结点p是尾结点,所以要使r指向p,才能让再次插入的
     35         //结点顺利执行第31行。
     36     }
     37 }
     38 
     39 
     40 // 获取链表中指定位置的数据元素
     41 int GetElem_LinkList(SLNode L, int i, int *e)
     42 {
     43     SLNode p;
     44     p = L->next;
     45     int j = 1;
     46 
     47     while (p && j < i)
     48     {
     49         p = p->next;
     50         ++j;
     51     }
     52 
     53     if (!p || j > i)
     54     {
     55         return ERROR;
     56     }
     57 
     58     *e = p->data;
     59     return OK;
     60 }
     61 
     62 
     63 // 在链表中指定位置插入数据
     64 int Isert_LinkList(SLNode L, int i, int* e)
     65 {
     66     SLNode p, s;
     67     p = L;
     68     int j = 0;
     69 
     70     while (p && j < i - 1)
     71     {
     72         p = p->next;
     73         ++j;
     74     }
     75 
     76     if (!p || j > i - 1)
     77     {
     78         return ERROR;
     79     }
     80 
     81     s = (SLNode)malloc(sizeof(SLL));
     82     s->data = *e;
     83     s->next = p->next;
     84     p->next = s;
     85 
     86     return OK;
     87 }
     88 
     89 
     90 // 删除链表中制定数据元素
     91 int Delete_LinkList(SLNode L, int i, int* e)
     92 {
     93     SLNode p, q;
     94     p = L;
     95     int j = 0;
     96 
     97     while (p->next && j < i - 1)
     98     {
     99         p = p->next;
    100         ++j;
    101     }
    102 
    103     if (!(p->next) || j > i - 1)
    104     {
    105         return ERROR;
    106     }
    107 
    108 
    109     q = p->next;
    110     p->next = q->next;
    111     *e = q->data;
    112 
    113     free(q);
    114     return OK;
    115 }
    116 
    117 
    118 // 显示链表元素的内容
    119 int Print_LinkList(SLNode L, char* s)
    120 {
    121     SLNode p;
    122 
    123     p = L->next;
    124     if (p == NULL)
    125     {
    126         cout << "该链表为空!" << endl;
    127         return ERROR;
    128     }
    129 
    130     while (p != NULL)
    131     {
    132         cout << p->data << " ";
    133         p = p->next;
    134     }
    135     cout << endl;
    136     return OK;
    137 }
    138 
    139 
    140 int main()
    141 {
    142     // 创建并初始化链表
    143     struct LNode L;
    144     cout << "请输入五个节点的数据" << endl;
    145     New_LinkList(&L, 5);
    146     Print_LinkList(&L, (char*)"初始化链表:");
    147 
    148     int s, v;
    149 
    150     // 插入数据
    151     cout << "请输入数据插入的位置和值:";
    152     cin >> s >> v;
    153     Isert_LinkList(&L, s, &v);
    154     Print_LinkList(&L, (char*)"插入后的节点数:");
    155 
    156 
    157     // 查询数据
    158     cout << "请输入数据查询的位置:";
    159     cin >> s;
    160     GetElem_LinkList(&L, s, &v);
    161     cout << "" << s << "个数据是:" << v << endl;
    162 
    163     // 删除出数据
    164     cout << "请输入数据删除的位置:";
    165     cin >> s;
    166     if (Delete_LinkList(&L, s, &v))
    167     {
    168         cout << "数据删除成功,你所删除的数据是:" << v << endl;
    169     }
    170     else
    171     {
    172         cout << "数据删除失败!" << endl;
    173     }
    174     Print_LinkList(&L, (char*)"删除后的链表:");
    175 
    176 
    177     return 0;
    178 }
  • 相关阅读:
    关于ARM CM3的启动文件分析
    curl 基本使用简介
    在windows下获取硬盘序列号(win7 32位,Windows Server 64位测试,希望在其他平台测试,遇到问题的网友留言分享)
    oracle 数据库用户登录相关
    ubuntu 下搭建一个python3的虚拟环境(用于django配合postgresql数据库开发)
    ubuntu下安装postgres
    python 中变量的命名规范
    python 各模块
    python中的model模板中的数据类型
    python编程中在ubuntu中安装虚拟环境及环境配置
  • 原文地址:https://www.cnblogs.com/yang901112/p/11674333.html
Copyright © 2011-2022 走看看