zoukankan      html  css  js  c++  java
  • 单链表

    【1】线性表的链式存储

    线性表的顺序存储结构特点:

    逻辑关系上相邻的两个元素在物理位置上也相邻;

    可以随机存取任一元素,它的存储位置可用一个简单直观的公式表示。

    然而,从另一个角度来看,这个优点也表明了这种存储结构的弱点:

    在做插入或删除操作时,需要移动大量的元素。

     

    线性表的链式存储不要求逻辑上相邻的元素在物理位置上也相邻。

    因此,它没有顺序存储结构所具有的弱点,但同时也失去随机存取的优点。

    另外一点:

    链式存储的存储空间采用动态分配,不会存在分配不够用或者浪费的情况。

    【2】链式存储结构

    链式存储结构如下图:

    【3】单链表的实现

    1. list.h 头文件

     1 #ifndef _STDAFX_H
     2 #define _STDAFX_H
     3 
     4 #include <iostream>
     5 #include <malloc.h>
     6 #include <assert.h>
     7 
     8 typedef enum { ERROR = 0, OK}  Status;
     9 
    10 typedef int ElemType;
    11 
    12 typedef struct _Node
    13 {
    14     ElemType data;
    15     struct _Node *next;
    16 } Node, *PNode, *Position;
    17 
    18 typedef struct 
    19 {
    20     PNode head, tail;
    21     size_t size;
    22 } List, *PList;
    23 
    24 
    25 PList    InitList();
    26 void    FreeNode(PNode p);
    27 PNode    BuyNode(ElemType x, PNode pN = NULL);
    28 
    29 void    Print_List(PList _list);
    30 void    DestroyList(PList _list);
    31 void    ClearList(PList _list);
    32 
    33 void    Push_Back(PList _list, ElemType x);
    34 void    Push_Front(PList _list, ElemType x);
    35 void    Pop_Back(PList _list);
    36 void    Pop_Front(PList _list);
    37 
    38 PNode    FindPreValue(PList _list, ElemType x);
    39 PNode    FindPos(PList _list, int pos);
    40 
    41 Status    Remove(PList _list, ElemType x);
    42 Status    RemoveAll(PList _list, ElemType x);
    43 
    44 Status    Erase(PList _list, size_t pos);
    45 
    46 Status    Insert(PList _list, int pos, ElemType x);
    47 
    48 void    Sort(PList _list);
    49 void    Reverse(PList _list);
    50 void    Merge(PList _list, PList _list1, PList _list2);
    51 void    Link(PList _list, PList _list1);
    52 
    53 size_t    Size(PList _list);
    54 
    55 #endif
    View Code

    2. list.cpp 实现文件

      1 #include "List.h"
      2 using namespace std;
      3 
      4 // 购买节点    
      5 PNode BuyNode(ElemType x, PNode n)
      6 {
      7     PNode s = (PNode)malloc(sizeof(Node));
      8     assert(NULL != s); //断言函数
      9     s->data = x;
     10     s->next = n;
     11     return s;
     12 }
     13 // 释放节点
     14 void FreeNode(PNode p)
     15 {
     16     free(p);
     17     p = NULL;
     18 }
     19 // 初始化链表
     20 PList InitList()
     21 {
     22     PList p = (PList)malloc(sizeof(List));
     23     assert(p != NULL);
     24     p->size = 0;
     25     p->head = p->tail = BuyNode(0, NULL); //表明是有头结点的单链表
     26     return p;
     27 }
     28 // 后面插入数据
     29 void Push_Back(PList _list, ElemType x)
     30 {
     31     _list->tail = _list->tail->next = BuyNode(x, NULL);
     32     _list->size += 1;
     33 }
     34 // 前面插入数据
     35 void Push_Front(PList _list, ElemType x)
     36 {
     37     PNode s =_list->head->next = BuyNode(x, _list->head->next);
     38     if (NULL == s->next)
     39     {
     40         _list->tail = s;
     41     }
     42     _list->size += 1;
     43 }
     44 // 打印链表
     45 void Print_List(PList _list)
     46 {
     47     PNode p = _list->head->next;
     48     cout << "元素个数: " << _list->size << endl;
     49     while (p != NULL)
     50     {
     51         cout << p->data << " ";
     52         p = p->next;
     53     }
     54     cout << endl;
     55 }
     56 // 清空链表
     57 void ClearList(PList _list)
     58 {
     59     PNode q = NULL;
     60     PNode s = _list->head->next;
     61     while (s != NULL)
     62     {
     63         q = s;
     64         s = s->next;
     65         free(q);    //FreeNode(q);
     66     }
     67     _list->size = 0;
     68     _list->head->next = NULL;
     69     _list->tail = _list->head;
     70 }
     71 // 摧毁链表
     72 void DestroyList(PList _list)
     73 {
     74     ClearList(_list);
     75     free(_list->head);
     76     free(_list);
     77 }
     78 // 后面弹出
     79 void Pop_Back(PList _list)
     80 {
     81     PNode p = _list->head;
     82     //循环定位找最后节点的前驱
     83     while (p->next != NULL && p->next->next != NULL)
     84     {
     85         p = p->next;
     86     }
     87 
     88     if (p->next != NULL)
     89     {
     90         PNode q = p->next;
     91         p->next = NULL;
     92         _list->tail = p;
     93         free(q);    //FreeNode(q);
     94         _list->size -= 1;
     95     }
     96 }
     97 // 前面弹出
     98 void Pop_Front(PList _list)
     99 {
    100     if (_list->head->next != NULL)
    101     {
    102         PNode q = _list->head->next;
    103         _list->head->next = q->next;
    104         free(q);    // FreeNode(p);
    105         _list->size -= 1;
    106         // 链表仅有一个元素
    107         if (NULL == _list->head->next)
    108         {
    109             _list->tail = _list->head;
    110         }
    111     }
    112 } 
    113 // 查找某值前驱
    114 PNode FindPreValue(PList _list, ElemType x)
    115 {
    116     PNode p = _list->head;
    117     while (p->next != NULL && p->next->data != x)
    118     {  
    119         p = p->next;
    120     }
    121     
    122     if (NULL == p->next)
    123     {
    124         p = NULL;
    125     }
    126 
    127     return p;
    128 }
    129 // 删除某值
    130 Status Remove(PList _list, ElemType x)
    131 {
    132     PNode p = FindPreValue(_list, x);  //找到前驱
    133     if (NULL == p) 
    134     {
    135         return ERROR;
    136     }
    137 
    138     PNode q = p->next;
    139     p->next = q->next;
    140 
    141     _list->size -= 1;
    142     return OK;
    143 }
    144 // 找某位置的节点
    145 PNode FindPos(PList _list, int pos)
    146 {
    147     if (pos < -1) 
    148         return NULL;
    149     if (-1 == pos) 
    150         return _list->head;
    151 
    152     int j = 0;
    153     PNode p = _list->head->next;
    154     while (j < pos && p != NULL)
    155     {
    156         p = p->next;
    157         ++j;
    158     }
    159     return p;
    160 }
    161 // 删除某位置的值
    162 Status Erase(PList _list, size_t pos)
    163 {
    164     if (pos >= _list->size)
    165     {
    166       cout<<"输入位置有误!!!"<<endl;
    167     }
    168     PNode p = FindPos(_list, pos - 1);   //找位置前驱
    169     if (p == NULL || p->next == NULL)   //前者说明空链表//后者说明末节点
    170     {
    171         return ERROR;
    172     }
    173 
    174     PNode q = p->next;
    175     p->next = q->next;
    176 
    177     if (p->next == NULL)
    178     {
    179         _list->tail = p;
    180     }
    181     FreeNode(q);
    182     --_list->size;
    183     return OK;
    184 }
    185 // 按位置插入数据
    186 Status Insert(PList _list, int pos, ElemType x)
    187 {
    188     PNode p = FindPos(_list, pos-1);
    189     if (NULL == p)
    190     {
    191         return ERROR;
    192     }
    193     p->next = BuyNode(x, p->next);//顺利衔接
    194     PNode s = p->next;
    195     if (s->next == NULL)
    196     {
    197         _list->tail = s;
    198     }
    199     ++_list->size;
    200     return OK;
    201 }
    202 // 逆置链表
    203 void Reverse(PList _list)
    204 {
    205     if (_list->size >= 2)
    206     {
    207         PNode s = _list->head->next;
    208         _list->tail = s;
    209         PNode p = s->next;
    210         s->next = NULL;
    211         while (p != NULL)
    212         {
    213             s = p;
    214             p = p->next;
    215             s->next = _list->head->next;
    216             _list->head->next = s;
    217         }
    218     }
    219 }
    220 // 合并
    221 void Merge(PList _list, PList _list1, PList _list2)
    222 {
    223     PNode r = _list->head;
    224     PNode p1 = _list1->head->next;
    225     PNode p2 = _list2->head->next;
    226     // 执行合并
    227     while (p1 != NULL && p2 != NULL)
    228     {
    229         if (p1->data <= p2->data)
    230         {
    231             r->next = p1;
    232             p1 = p1->next;
    233         }
    234         else
    235         {
    236             r->next = p2;
    237             p2 = p2->next;
    238         }
    239         r = r->next;
    240     }
    241     // _list2先合并完成
    242     if (p1 != NULL)
    243     {
    244         r->next = p1;
    245         _list->tail = _list1->tail;
    246     }
    247     // _list1先合并完成
    248     if (p2 != NULL)
    249     {
    250         r->next = p2;
    251         _list->tail = _list2->tail;
    252     }
    253     // 合并数量
    254     _list->size = _list1->size + _list2->size;
    255     // 收尾
    256     _list1->head->next = NULL;
    257     _list1->tail = _list1->head;
    258     _list1->size = 0;
    259 
    260     _list2->head->next = NULL;
    261     _list2->tail = _list2->head;
    262     _list2->size = 0;
    263 }
    264 //连接
    265 void Link(PList _list, PList _list1)
    266 {
    267     _list->tail->next = _list1->head->next;
    268     _list->tail = _list1->tail;
    269     _list->size += _list1->size;
    270 
    271     _list1->head->next = NULL;
    272     _list1->tail = _list1->head;
    273     _list1->size = 0;
    274 }
    275 
    276 /*
    277  * 逆置方式2
    278 void Reverse(PList _list)
    279 {
    280     PNode r = _list->head->next;
    281     PNode s = r->next;
    282     PNode p = s->next;
    283     r->next = NULL;
    284     _list->tail = r;
    285     while (p != NULL)
    286     {
    287         s->next = r;
    288         r = s;
    289         s = p;
    290         p = p->next;
    291     }
    292     s->next = r;
    293     _list->head->next = s;
    294 }
    295 */
    View Code

    3. listmain.cpp 测试文件

      1 #include "List.h"
      2 using namespace std;
      3 
      4 #define UM_QUIT          0
      5 #define UM_INPUTR     1
      6 #define UM_INPUTH     2
      7 #define UM_PRINT      3
      8 #define UM_ERASE      4
      9 #define UM_REMOVE     5
     10 #define UM_POPFRONT   6
     11 #define UM_POPBACK    7
     12 #define UM_INSERT     8
     13 #define UM_REVERSE    9
     14 #define UM_MERGE      10
     15 #define UM_LINK          11
     16 
     17 #define ListNum0      0
     18 #define ListNum1      1
     19 #define ListNum2      2
     20 
     21 void main()
     22 {
     23     PList mylist, mylist1, mylist2;
     24     int select = 1, pos = 0, num = 0;
     25     ElemType item;
     26     mylist = InitList();
     27     mylist1 = InitList();
     28     mylist2 = InitList();
     29     while (select != 0)
     30     {
     31         cout << "		*********************菜单********************* " << endl;
     32         cout << "		**    1.输入数据r    2.输入数据h " << endl;
     33         cout << "		**    3.打印数据     4.位置删除 " << endl;
     34         cout << "		**    5.删除某值     6.前面弹出 " << endl;
     35         cout << "		**    7.后面弹出     8.位置插入 " << endl;
     36         cout << "		**    9.逆置链表     10.合并链表 " << endl;
     37         cout << "		**    11.连接链表    0.退出         " << endl;
     38         cout << "		**********************************************				" << endl;
     39         cout << "请选择" << endl;
     40         cin >> select;
     41         switch (select)
     42         {
     43         case UM_QUIT:
     44             break;
     45         case UM_INPUTR:
     46             {
     47                 cout << "请输入要操作的链表:" << endl;
     48                 cin >> num;
     49                 switch (num)
     50                 {
     51                 case ListNum0:
     52                     cout << "请输入数据并以-1结束" << endl;
     53                     while (cin >> item, item != -1)
     54                     {
     55                         Push_Back(mylist, item);
     56                     }
     57                     break;
     58                 case ListNum1:
     59                     cout << "请输入数据并以-1结束" <<endl;
     60                     while(cin >> item, item != -1)
     61                     {
     62                         Push_Back(mylist1, item);
     63                     }
     64                     break;
     65                 case ListNum2:
     66                     cout << "请输入数据并以-1结束" << endl;
     67                     while(cin >> item, item != -1)
     68                     {
     69                         Push_Back(mylist2,item);
     70                     }
     71                     break;
     72                 default:
     73                     cout << "选择错误 请重新选择" << endl;
     74                     break;
     75                 }
     76             }
     77             break;
     78         case UM_INPUTH:
     79             {
     80                 cout << "请输入要操作的链表:" << endl;
     81                 cin >> num;
     82                 switch (num)
     83                 {
     84                 case ListNum0:
     85                     cout << "请输入数据并以-1结束" << endl;
     86                     while(cin  >>item, item != -1)
     87                     {
     88                         Push_Front(mylist, item);
     89                     }
     90                     break;
     91                 case ListNum1:
     92                     cout << "请输入数据并以-1结束" <<endl;
     93                     while(cin>>item, item != -1)
     94                     {
     95                         Push_Front(mylist1, item);
     96                     }
     97                     break;
     98                 case ListNum2:
     99                     cout << "请输入数据并以-1结束" << endl;
    100                     while(cin >> item, item != -1)
    101                     {
    102                         Push_Front(mylist2, item);
    103                     }
    104                     break;
    105                 default:
    106                     cout << "选择错误 请重新选择" <<endl;
    107                     break;
    108                 }
    109             }
    110             break;
    111         case UM_PRINT:
    112             {
    113                 cout << "请输入要操作的链表:" << endl;
    114                 cin >> num;
    115                 switch (num)
    116                 {
    117                 case ListNum0:
    118                     Print_List(mylist);
    119                     break;
    120                 case ListNum1:
    121                     Print_List(mylist1);
    122                     break;
    123                 case ListNum2:
    124                     Print_List(mylist2);
    125                     break;
    126                 default:
    127                     cout << "选择错误 请重新选择" << endl;
    128                     break;
    129                 }
    130             }
    131             break;
    132         case UM_ERASE:
    133             cout << "请输入位置:" << endl;
    134             cin >> pos;
    135             Erase(mylist, pos);
    136             break;
    137         case UM_REMOVE:
    138             cout << "请输入要删除的数据:" <<endl;
    139             cin >> item;
    140             Remove(mylist, item);
    141             break;
    142         case UM_POPFRONT:
    143             Pop_Front(mylist);
    144             break;
    145         case UM_POPBACK:
    146             Pop_Back(mylist);
    147             break;
    148         case UM_INSERT:
    149             cout << "请输入要插入的数据及位置信息:" << endl;
    150             cin >> item, pos;
    151             Insert(mylist, pos, item);
    152             break;
    153         case UM_REVERSE:
    154             Reverse(mylist);
    155             break;
    156         case UM_MERGE:
    157             Merge(mylist, mylist1, mylist2);
    158             break;
    159         case UM_LINK:
    160             Link(mylist, mylist1);
    161             break;
    162         default:
    163             cout << "选择错误! 请重新选择" << endl;
    164             break;
    165         }
    166     }
    167     DestroyList(mylist);
    168 }
    View Code

    以上代码分为三部分:头文件,实现文件,测试文件。

    当时运行环境为VS2010。

    Good Good Study, Day Day Up.

    顺序  选择  循环  总结 

  • 相关阅读:
    对拍程序的写法
    单调队列模板
    [bzoj1455]罗马游戏
    KMP模板
    [bzoj3071]N皇后
    [bzoj1854][SCOI2010]游戏
    Manacher算法详解
    [bzoj2084][POI2010]Antisymmetry
    Python_sklearn机器学习库学习笔记(一)_一元回归
    C++STL学习笔记_(1)string知识
  • 原文地址:https://www.cnblogs.com/Braveliu/p/3452258.html
Copyright © 2011-2022 走看看