• 第十五章 链表


    1. 什么是链表

    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,链表比较方便插入和删除操作。

    2. 结构体链表+联合体

     1 struct book
     2 {    
     3     int num;
     4     float price;
     5     book * next;
     6     union MyUnion        //联合体大小等于最大的变量大小
     7     {
     8         int ClassID;
     9         char ADD[20];
    10     };
    11 }; //默认公有,而class默认私有

     

    3. 静态链表

    4. 动态链表

    5. 动态链表的建立

    先建立一个节点(两部分①数据部分②next指针)。再建立三个指针head(外面建立),p1,p2;

    6. 解决输入字符造成死循环的问题

    解决方法:

    ① cin.clear();

        cin.ignore();

    cin.ignore() 接受两个参数,第一个参数是你要清楚输入缓冲区中元素的个数(默认时为1),第二个参数的作用:在清楚缓冲区时如果遇到的元素与参数相同时则停止此操作。 cin.sync() 用于清楚整个输入流的缓冲区 cin.clear() 用于重置错误标志(默认时),cin出现错误时用它来重置。(一般清楚缓冲区之前,程序前面会出现cin错误。最好在清楚了缓冲区后重置错误位)

     1 //检测输入的是否是价格(0到9或小数)
     2 bool check(string str)
     3 {
     4     int i,j=0;           //增加变量j来保存"."出现的次数
     5     if (str[0]=='.')    //假如第一个字符是'.'
     6         return false;    //不是数字,返回false
     7     for(i = 0;i<str.length();i++)  //增加for循环来检测"."出现的次数
     8         //str.length()  调用string类测量str的长度
     9     {
    10 
    11         if((str[i]=='.')) //假如"."出现
    12 
    13             j++;            //将j自加
    14     }
    15     if (j>1)                 //假如"."超过1个
    16         return  false;     //不是数字,返回false
    17     for(i = 0;i<str.length();i++)
    18         if((str[i]>'9' || str[i]<'0')&&(str[i]!='.'))//如果不是0到9或者小数点的话就返回false
    19             return false;
    20     return true;
    21 }

    atoi        //char型转换成int型

    atof           //char型转换成float型

    c_str()       //c++类string转换成c类

          // c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同. 

    这是为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式。

    7. 动态链表的显示

    8. 动态链表的删除

    9. 动态链表的插入

    10. 演示尾插法

    11. 前插法

    12. 中间插法

    13. 链表统计

    14. 使用链表

      1 /**
      2 数组与链表的区别:数组易随机访问,链表易插入和删除
      3 链表组成:储存数据元素的数据域,储存下一结点地址的指针域
      4 链表易于插入与删除
      5 lists 的用法?????????????????????
      6 */
      7 #include<iostream>
      8 #include <string>
      9 using namespace std;
     10 struct book        //第一步: 用于建立节点。 class 默认为私有 struct 默认为公有
     11                 //节点组成:①数据域  ②指针域(*next)
     12 {
     13     int num;    //图书编号
     14     float price;    //图书价格
     15     book *next;
     16 };
     17 class list
     18 {
     19 private:
     20     book *head;
     21 public:
     22     list(){head = NULL;}
     23     void insertlist(int bnum,float bprice);        //插入
     24     void deletelist(int dnum);                    //删除
     25     void outputlist();                            //显示
     26     void countlist();                    //统计链表数
     27     bool checknum(string x);                //检测图书编号输入是否正确
     28     bool checkprice(string y);                //检测图书价格输入是否正确
     29 };
     30 void list::insertlist(int bnum,float bprice)//插入  操作对象时Pb指向的节点
     31 {
     32     book *Pf,*Pm,*Pb;//Pf为上一结点指针,Pm为本结点指针,Pb为要被插入结点指针
     33     Pm=head;//将本结点Pm设为第一个结点(只是为了方便阅读,其实完全可以用head代替)
     34     Pb= new book;    //建立要插入的结点
     35     Pb->num = bnum;
     36     Pb->price = bprice;
     37     //error*******if(head->num == NULL) //因为没有head->num不是指针
     38     if(head == NULL)//若为空链表,则将被插入结点设为第一个结点(建立第一个结点)
     39     {
     40         head = Pb;
     41         Pb->next = NULL;
     42     }
     43     else if(bnum < head->num)//若要插入的结点编号小于第一个结点的编号(前插)
     44     {
     45         Pb->next = head;
     46         head = Pb;
     47     }
     48     else
     49     {
     50         while((bnum >= Pm->num) && (Pm->next != NULL))//遍历满足条件的结点 就等于Pm++ //确立Pb所处的位置,即Pf,Pm的位置
     51         {
     52             Pf = Pm;
     53             Pm = Pm->next;
     54         }
    55 if(bnum >= Pm->num)//尾插 只要上面的wile循环会停 这个if就不会进来 56 { 57 Pm->next = Pb; 58 Pb->next = NULL; 59 } 60 else //中插 61 { 62 Pf->next = Pb; 63 Pb->next = Pm; 64 } 65 } 66 67 } 68 void list::deletelist(int dnum)//删除 操作对象时Pm指向的节点 69 { 70 book *Pf,*Pm;//Pf为上一结点指针,Pm为本结点指针 71 Pm=head; 72 if(head == NULL) // 若为空结点 73 { 74 cout<<"图书储存为空"<<endl; 75 return; 76 } 77 if(Pm->num == dnum) //若被删除的为第一个指针 78 { 79 head = Pm->next; 80 delete Pm; 81 } 82 else 83 { 84 while(Pm->num != dnum && Pm->next != NULL)//Pm++ 85 { 86 Pf = Pm; 87 Pm = Pm->next; 88 } 89 if(Pm->num == dnum) 90 { 91 Pf->next = Pm->next; 92 delete Pm; 93 } 94 else 95 { 96 cout<<"没有你要删除的图书"<<endl; 97 } 98 } 99 } 100 void list::outputlist() 101 { 102 book *Pm; 103 Pm = head; 104 if(head == NULL) 105 { 106 cout<<"链表为空链表,请选择是否插入链表"<<endl; 107 return; 108 } 109 while(Pm != NULL) 110 { 111 cout<<"图书编号:"<<Pm->num<<' '; 112 113 cout<<"图书价格:"<<Pm->price<<endl; 114 Pm=Pm->next; //Pm++ 115 } 116 cout<<endl; 117 } 118 void list::countlist() 119 { 120 book *Pm; 121 Pm = head; 122 int countnum = 0; 123 while(Pm != NULL) 124 { 125 countnum++; 126 Pm=Pm->next; 127 } 128 cout<<"图书统计为:"<<countnum<<""<<endl; 129 cout<<endl; 130 131 } 132 bool list::checknum(string x) 133 { 134 int i,j=0; //增加变量j来保存"."出现的次数 135 136 for(i = 0;i<x.length();i++) 137 { 138 if(x[i]>'9' || x[i]<'0')//如果不是0到9或者小数点的话就返回false 139 { 140 cout<<"你输入的不是纯数字,请重新输入"<<endl; 141 return false; 142 } 143 } 144 return true; 145 } 146 bool list::checkprice(string y) 147 { 148 int i,j=0; //增加变量j来保存"."出现的次数 149 /*if (y[0]=='.') //假如第一个字符是'.' 150 { 151 cout<<"你输入的不是数字,请重新输入"<<endl; 152 return false; //不是数字,返回false 153 }*/ 154 for(i = 0;i<y.length();i++) //增加for循环来检测"."出现的次数 155 { 156 if((y[i]=='.')) //假如"."出现 157 j++; //将j自加 158 } 159 if (j>1) //假如"."超过1个 160 { 161 cout<<"你输入的不是数字,请重新输入"<<endl; 162 return false; //不是数字,返回false 163 } 164 165 for(i = 0;i<y.length();i++) 166 { 167 if((y[i]>'9' || y[i]<'0')&&(y[i]!='.'))//如果不是0到9或者小数点的话就返回false 168 { 169 cout<<"你输入的不是数字,请重新输入"<<endl; 170 return false; 171 } 172 } 173 return true; 174 } 175 176 int main() 177 { 178 list A_student; 179 cout<<"创建一个叫A_student的图书链表"<<endl; 180 while(1) 181 { 182 cout<<"1-显示列表"<<"2-插入列表"<<"3-删除列表"<<"4-统计列表"<<"0-退出列表"<<endl; 183 int n; 184 string xnum,xprice; 185 bool breaklist=false; 186 cin>>n; //此处不能用cin.get(); 187 cin.clear(); 188 cin.ignore(); //解决输入字符造成死循环的问题 189 switch(n) 190 { 191 case 1:A_student.outputlist(); 192 break; 193 case 2:do 194 { 195 cout<<"您要输入的图书编号是:"<<endl; 196 cin>>xnum; 197 }while(!A_student.checknum(xnum)); 198 do 199 { 200 cout<<"您要输入的图书价格是:"<<endl; 201 cin>>xprice; 202 }while(!A_student.checkprice(xprice)); 203 A_student.insertlist(atoi(xnum.c_str()),atof(xprice.c_str()));//将string型转化成asii型 204 205 break;//此处要使用多线程,才能保证连续插入列表????????????????????????? 206 case 3:do 207 { 208 cout<<"您要删除的图书编号是:"<<endl; 209 cin>>xnum; 210 }while(!A_student.checknum(xnum)); 211 A_student.deletelist(atoi(xnum.c_str())); 212 break; 213 case 4:A_student.countlist(); 214 break; 215 case 0: breaklist = true; 216 break; 217 default:cout<<"请输入菜单内的数字:"<<endl; 218 break; 219 } 220 if(breaklist == true) 221 break; 222 } 223 return 0; 224 }

    15.1  链表使用案例之走迷宫

    15.2  设置项目

    15.3  创建派生类

    创建一个win32窗口:

    ①创建Win32 Application→②添加头文件夹并在其添加MFC的头文件名(#inlcude”afxwin.h”)→③创建资源文件(没有外部资源也要创建)→④设置资源包含(添加外部资源的头文件名)→⑤设置类向导→⑥设置项目

    15.4  定义应用程序对象

    15.5  初始化函数

    15.6  创建窗口

    15.7  显示窗口

    15.8  更新窗口

    15.9   GDI类

    15.10  加载位图

    15.11   LoadImage函数

    15.12  句柄是什么

    句柄是指向内存地址的指针,为了适应虚拟内存技术,存储变动的内存地址。

    15.13  显示图片

    15.19  小知识点

    15.20  动画

    15.24  键盘控制人物移动

    15.28  迷宫墙壁

    15.32  走迷宫

    15.33  用链表记录行走路线

    本章总结:

  • 相关阅读:
    使用 VS Code 开发和调试 Burp Suite 扩展
    后渗透神器 Empire 基础用法
    5种语言的按钮事件 断点
    X64下MmIsAddressValid的逆向及内存寻址解析
    x64 内存共享区 KUSER_SHARED_DATA
    内存映射+远线程 调用游戏CALL
    C语言运算符总结
    x32 x64的不同传参方式
    内存占用的一些小问题
    x64分页机制 9
  • 原文地址:https://www.cnblogs.com/zenseven/p/3783676.html
Copyright © 2020-2023  润新知