• 2.3线性表的链式存储结构


    链表

    增加O(1)

    删除O(1)

    线性查找O(n)

    修改O(1)

    插入O(1)

    1 head

    2 头结点

    3 开始结点

    4 终端结点

    5 尾指针

    1 head

    指向头结点的指针变量

    2 头结点

    开始结点,即是第一个有效结点之前的那个结点

    头结点并不存储有效数据

    加头结点的目的主要是为了方便对链表的操作

    3 开始结点

    第一个有效结点

    4 终端结点

    最后一个有效结点

    5 尾指针

    指向终端结点的指针变量

    分类:

    单链表

    双向链表:每一个结点有两个指针域

    循环链表:能通过任何一个结点找到其他所有的结点

    非循环链表

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <stdbool.h>
      4 
      5 struct node//说明一个结构体
      6 {
      7     int data;
      8     struct node * next;
      9 };
     10 
     11 typedef struct node LinkNode;//简写
     12 
     13 LinkNode * create();//创建一个非循环单链表,并将该链表的头结点地址赋给head
     14 void add(LinkNode * head, int data);//尾部插入
     15 void print1(LinkNode * head);//遍历,递归
     16 void print2(LinkNode * head);//遍历,非递归
     17 bool is_empty(LinkNode * head);//判断链表是否为空,1为空,0为非空
     18 int length_list(LinkNode * head);//返回链表结点数量
     19 bool InsertList(LinkNode * head, int pos, int val);//在第pos个结点的前面插入一个新的结点,pos从1开始计算,该结点的值为val
     20 bool DeleteList(LinkNode * head, int pos, int *val);//删除第pos个结点
     21 void sort_list(LinkNode * head);//排序
     22 
     23 void main()
     24 {
     25     LinkNode * head = NULL;//头指针
     26     int val = 0;//保存删除的元素
     27 
     28     head = create();//创建一个非循环单链表,并将该链表的头结点地址赋给head
     29 
     30     printf("判断链表是否为空%d
    ", is_empty(head));//判断链表是否为空,1为空,0为非空
     31 
     32     add(head, 4);//尾部插入
     33     add(head, 3);
     34     add(head, 2);
     35     add(head, 1);
     36 
     37     print1(head);//遍历,递归
     38     printf("
    ");
     39 
     40     printf("判断链表是否为空%d
    ", is_empty(head));//判断链表是否为空,1为空,0为非空
     41     printf("返回链表结点数量%d
    ", length_list(head));//返回链表结点数量
     42 
     43     //sort_list(head);//链表排序
     44     //traverse_list1(head);//遍历,递归
     45 
     46     if (InsertList(head, 4, 33))//在第pos个结点的前面插入一个新的结点,pos从1开始计算,该结点的值为val
     47     {
     48         printf("插入成功
    ");
     49         print1(head);//遍历,递归
     50         printf("
    ");
     51     }
     52     else
     53     {
     54         printf("插入失败
    ");
     55     }
     56 
     57     if (DeleteList(head, 4, &val))//删除第pos个结点
     58     {
     59         printf("删除成功,删除的元素是:%d
    ", val);
     60         print1(head);//遍历,递归
     61         printf("
    ");
     62     }
     63     else
     64     {
     65         printf("删除失败
    ");
     66     }
     67 
     68     system("pause");
     69 }
     70 
     71 LinkNode * create()//创建一个非循环单链表,并将该链表的头结点地址赋给head
     72 {
     73     LinkNode * head = (LinkNode *)malloc(sizeof(LinkNode));
     74     if (head == NULL)
     75     {
     76         printf("创建链表失败,内存分配失败
    ");
     77         return NULL;
     78     }
     79     else
     80     {
     81         head->next = NULL;
     82         return head;
     83     }
     84 }
     85 
     86 void add(LinkNode * head, int data)//尾部插入
     87 {
     88     LinkNode * new = (LinkNode *)malloc(sizeof(LinkNode));//第1步,创建指针new,用于存储新数据
     89     if (new == NULL)
     90     {
     91         printf("尾部插入失败,内存分配失败
    ");
     92         return;
     93     }
     94     else
     95     {
     96         new->data = data;
     97         new->next = NULL;
     98     }
     99 
    100     LinkNode * p = head;//第2步,创建指针p,用于移动
    101     if (p == NULL)
    102     {
    103         printf("头指针为空
    ");
    104         return;
    105     }
    106     else
    107     {
    108         while (p->next != NULL)//遍历
    109         {
    110             p = p->next;
    111         }
    112         p->next = new;//第3步,指针p指向指针new
    113     }
    114 }
    115 
    116 void print1(LinkNode * head)//遍历,递归
    117 {
    118     if (head->next == NULL)
    119     {
    120         return;
    121     }
    122     else
    123     {
    124         printf("%d ", head->next->data);
    125         print1(head->next);
    126     }
    127 }
    128 
    129 void print2(LinkNode * head)//遍历,非递归
    130 {
    131     LinkNode * p = head;
    132     while (p->next)
    133     {
    134         printf("%d ", p->next->data);
    135         p = p->next;
    136     }
    137     printf("
    ");
    138 }
    139 
    140 bool is_empty(LinkNode * head)//判断链表是否为空,1为空,0为非空
    141 {
    142     if (head->next)
    143     {
    144         return false;
    145     }
    146     else
    147     {
    148         return true;
    149     }
    150 }
    151 
    152 int length_list(LinkNode * head)//返回链表结点数量
    153 {
    154     LinkNode * p = head;
    155     int count = 0;//保存结点数量
    156     while (p->next)
    157     {
    158         count++;
    159         p = p->next;
    160     }
    161     return count;
    162 }
    163 
    164 bool InsertList(LinkNode * head, int pos, int val)//在第pos个结点的前面插入一个新的结点,pos从1开始计算,该结点的值为val
    165 {
    166     int i = 0;
    167     LinkNode * p = head;
    168 
    169     while (p != NULL && i < pos - 1)//
    170     {
    171         p = p->next;
    172         i++;
    173     }
    174 
    175     if (i > pos - 1 || p == NULL)//
    176     {
    177         printf("插入结点失败
    ");
    178         return false;
    179     }
    180 
    181     LinkNode * new = (LinkNode *)malloc(sizeof(LinkNode));
    182 
    183     if (new == NULL)
    184     {
    185         printf("插入结点失败,内存分配失败
    ");
    186         return false;
    187     }
    188 
    189     new->data = val;
    190     new->next = NULL;
    191 
    192     LinkNode * q = p->next;//创建新结点q指向p的下一个
    193     p->next = new;
    194     new->next = q;
    195 
    196     return true;
    197 }
    198 
    199 bool DeleteList(LinkNode * head, int pos, int * val)//删除第pos个结点
    200 {
    201     int i = 0;
    202     LinkNode * p = head;
    203 
    204     while (p != NULL && i < pos - 1)//
    205     {
    206         p = p->next;
    207         i++;
    208     }
    209 
    210     if (i > pos - 1 || p == NULL)//
    211     {
    212         printf("插入结点失败
    ");
    213         return false;
    214     }
    215 
    216     LinkNode * q = p->next;//保存即将要删除的结点
    217     *val = q->data;//保存即将要删除的结点的值
    218 
    219     p->next = p->next->next;//跳过即将要删除的结点
    220     free(q);
    221     q = NULL;
    222 
    223     return true;
    224 }
    225 
    226 void sort_list(LinkNode * head)//链表排序
    227 {
    228     int i, j;
    229     int temp;
    230     LinkNode * p, *q;
    231     int length = length_list(head);//返回链表结点数量
    232 
    233     for (i = 0, p = head->next; i < length - 1; i++, p = p->next)//冒泡
    234     {
    235         for (j = i + 1, q = p->next; j < length; j++, q = q->next)
    236         {
    237             if (p->data > q->data)
    238             {
    239                 temp = p->data;
    240                 p->data = q->data;
    241                 q->data = temp;
    242             }
    243         }
    244     }
    245 }

    C++实现链表,无头结点

    重点掌握

    void sort();//排序,冒泡

    void deletesame();//删除相同的元素

    void rev();//链表逆转

    头文件

     1 #pragma once
     2 #include "Node.h"
     3 
     4 template <class T>
     5 class List
     6 {
     7 public:
     8     Node<T> *pHead;
     9 public:
    10     List();
    11     void add(T t);//尾部插入
    12     void show();//打印
    13     Node<T> *find(T t);//查找
    14     void change(Node<T> *p, T t);//修改
    15     int getnum();//获取个数
    16     bool delete1(T t);//删除元素
    17 
    18     void sort();//排序,冒泡
    19     void deletesame();//删除相同的元素
    20     void rev();//链表逆转
    21 
    22     void insert(T oldt, T newt);//前插
    23     bool clear();//清空
    24     void merge(List & list);//归并
    25     ~List();
    26 };

    源文件

      1 #include "List.h"
      2 
      3 template <class T>
      4 List<T>::List()//构造函数
      5 {
      6     this->pHead = nullptr;
      7     std::cout << "链表创建" << std::endl;
      8 }
      9 
     10 template <class T>
     11 void List<T>::add(T t)//尾部插入
     12 {
     13     Node<T> *pnew = new Node<T>;//分配结点
     14     pnew->t = t;
     15     pnew->pNext = nullptr;
     16 
     17     if (pHead == NULL)
     18     {
     19 
     20         this->pHead = pnew;//头结点
     21     }
     22     else
     23     {
     24         Node<T> *p = pHead;//获取开始结点位置
     25         while (p->pNext != nullptr)//循环到尾部
     26         {
     27             p = p->pNext;
     28         }
     29         p->pNext = pnew;
     30     }
     31 }
     32 
     33 template <class T>
     34 void List<T>::show()//打印
     35 {
     36     Node<T> *p = pHead;//获取开始结点位置
     37     while (p != nullptr)//循环到尾部
     38     {
     39         std::cout << p->t << " ";
     40         p = p->pNext;
     41     }
     42     std::cout << "
    ";
     43 }
     44 
     45 template <class T>
     46 Node <T> *List<T>::find(T t)//查找
     47 {
     48     Node<T> *p = pHead;//获取开始结点位置
     49     while (p != nullptr)//循环到尾部
     50     {
     51         if (t == p->t)
     52         {
     53             return p;
     54         }
     55         p = p->pNext;
     56     }
     57     return nullptr;
     58 }
     59 
     60 template <class T>
     61 void List<T>::change(Node<T> *p, T newt)//修改
     62 {
     63     if (nullptr == p)
     64     {
     65         return;
     66     }
     67     else
     68     {
     69         p->t = newt;
     70     }
     71 }
     72 
     73 template <class T>
     74 int List<T>::getnum()//获取结点数量
     75 {
     76     int i;
     77     Node<T> *p = pHead;//获取开始结点位置
     78     while (p != nullptr)//循环到尾部
     79     {
     80         i++;
     81         p = p->pNext;
     82     }
     83     return i;
     84 }
     85 
     86 template <class T>
     87 bool List<T>::delete1(T t)//删除元素
     88 {
     89     Node<T> *p = this->find(t);
     90     if (nullptr == p)
     91     {
     92         return false;
     93     }
     94     else
     95     {
     96         if (pHead == p)//开始结点
     97         {
     98             pHead = p->pNext;
     99             delete p;
    100         }
    101         else
    102         {
    103             Node<T> *p1, *p2;//p1在前,p2在后
    104             p1 = pHead;
    105             p2 = p1->pNext;
    106 
    107             while (p2 != p)
    108             {
    109                 p1 = p2;
    110                 p2 = p2->pNext;
    111             }
    112 
    113             p1->pNext = p2->pNext;//跳过p2
    114             delete p2;
    115         }
    116         return true;
    117     }
    118 }
    119 
    120 template <class T>
    121 void List<T>::sort()//排序,冒泡
    122 {
    123     for (Node<T>*p1 = pHead; p1 != nullptr; p1 = p1->pNext)
    124     {
    125         for (Node<T>*p2 = pHead; p2 != nullptr; p2 = p2->pNext)
    126         {
    127             if (p1->t < p2->t)
    128             {
    129                 T temp = p1->t;
    130                 p1->t = p2->t;
    131                 p2->t = temp;
    132             }
    133         }
    134     }
    135 }
    136 
    137 template <class T>
    138 void List<T>::deletesame()//删除链表相同的元素
    139 {
    140     Node<int>*p1, *p2;
    141     p1 = pHead;//p1在前
    142     p2 = pHead->pNext;//p2在后
    143 
    144     while (p2)
    145     {
    146         if (p1->t == p2->t)//如果p1的关键字和p2的关键字相同
    147         {
    148             p1->pNext = p2->pNext;//跳过p2
    149             delete p2;//删除p2
    150             p2 = p1->pNext;//p2仍然是p1后面
    151         }
    152         else
    153         {
    154             p1 = p2;//p1继续向后
    155             p2 = p2->pNext;//p2继续向后
    156         }
    157     }
    158 }
    159 
    160 template <class T>
    161 void List<T>::rev()//链表逆转
    162 {
    163     if (pHead == nullptr || pHead->pNext == nullptr)//如果开始结点为空,或者只有一个结点,没有必要逆转
    164     {
    165         return;
    166     }
    167     else
    168     {
    169         Node<T>*p1, *p2, *p3;//p1前p2中p3后
    170         p1 = pHead;
    171         p2 = p1->pNext;
    172         while (p2)
    173         {
    174             p3 = p2->pNext;//p3在p2后
    175             p2->pNext = p1;//p2往前指向p1
    176             p1 = p2;//p1向前
    177             p2 = p3;//p2向前
    178         }
    179         pHead->pNext = nullptr;
    180         pHead = p1;
    181     }
    182 }
    183 
    184 template <class T>
    185 void List<T>::insert(T oldt, T newt)//在某个元素前插
    186 {
    187     Node<T>*p = find(oldt);
    188     if (p)
    189     {
    190         Node<T>*p1, *p2;
    191         p1 = pHead;
    192         p2 = p1->pNext;
    193         while (p2 != p)
    194         {
    195             p1 = p2;
    196             p2 = p2->pNext;
    197         }
    198         Node<T>*pnew = new Node<T>;
    199         pnew->t = newt;
    200         pnew->pNext = p2;
    201         p1->pNext = pnew;
    202     }
    203 }
    204 
    205 template <class T>
    206 bool List<T>::clear()//清空
    207 {
    208     if (!pHead)
    209     {
    210         return false;
    211     }
    212     else
    213     {
    214         Node<int>*p1, *p2;//p1在前,p2在后
    215         p1 = pHead->pNext;
    216 
    217         while (p1)
    218         {
    219             p2 = p1->pNext;
    220             delete p1;
    221             p1 = p2;
    222         }
    223 
    224         delete pHead;
    225         pHead = nullptr;
    226 
    227         return true;
    228     }
    229 }
    230 
    231 template <class T>
    232 void List<T>::merge(List & list)//归并
    233 {
    234     Node<T>*p = pHead;//获取开始结点
    235     while (p->pNext)//循环到尾部
    236     {
    237         p = p->pNext;
    238     }
    239     p->pNext = list.pHead;
    240 }
    241 
    242 template <class T>
    243 List<T>::~List()//析构函数
    244 {
    245     std::cout << "链表销毁" << std::endl;
    246 }
  • 相关阅读:
    追求一个人怎么这么难
    基于PHPstream扩展手动实现一个redis客户端
    常见final修饰类
    位运算
    HTTP Status 404
    Hibernate Junit 运行报错:org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment
    根据银行卡号码获取银行卡归属行以及logo图标
    进程间通信IPC(InterProcess Communication)
    脏读、幻读、不可重复读和可重复读
    数据库锁知识总结
  • 原文地址:https://www.cnblogs.com/denggelin/p/5683289.html
走看看 - 开发者的网上家园