实现单链表的各种基本运算

  1 #include<iostream>
  2 using namespace std;
  3
  4 #define OK 1
  5 #define ERROR 0
  6 #define OVERFLOW -2
  7 typedef int Status;        //Status 是函数返回值类型,其值是函数结果状态代码。
  8 typedef int ElemType;     //ElemType 为可定义的数据类型,此设为int类型
  9
 10 typedef struct LNode
 11 {
 12     ElemType data;    //结点的数据域
 13     struct LNode *next;        //结点的指针域
 14 }LNode,*LinkList;  //LinkList为指向结构体LNode的指针类型
 15
 16
 17 Status InitList_L(LinkList &L){    //算法2.5 单链表的初始化
 18     //构造一个空的单链表L
 19     L=new LNode;    //生成新结点作为头结点,用头指针L指向头结点
 20     L->next=NULL;    //头结点的指针域置空
 21     return OK;
 22 }
 23
 24 Status ListInsert_L(LinkList &L,int i,ElemType &e){ //算法2.8 单链表的插入
 25     //在带头结点的单链表L中第i个位置之前插入元素e
 26     int j;
 27     LinkList p,s;
 28     p=L;j=0;
 29     while(p && j<i-1){p=p->next;++j;} //刚好指向第i-1个节点
 30     if(!p||j>i-1)    return ERROR;    //i大于表长+1或者小于1  当p不为空时如果i小于1的话则插入失败,如果p为空的话表明i大于表长
 31     s=new LNode;    //生成新结点s  p指向当前第i-1的节点位置
 32     s->data=e;        //将结点s的数据域置为e
 33     s->next=p->next; //将结点s插入L中
 34     p->next=s;
 35     return OK;
 36 }//ListInsert_L
 37
 38 void CreateList_F(LinkList &L,int n){ //算法2.10 (前插法)创建单链表
 39     //逆位序输入n个元素的值,建立到头结点的单链表L
 40     LinkList p;
 41     L=new LNode;
 42     L->next=NULL;     //先建立一个带头结点的空链表
 43     cout<<"请输入 "<<n<<" 个数(以空格隔开,按回车结束):";
 44     for(int i=n;i>0;--i){
 45         p=new LNode;     //生成新结点
 46         cin>>p->data;   //输入元素值
 47         p->next=L->next;
 48         L->next=p;  //插入到表头
 49     }
 50 }//CreateList_F
 51
 52 void CreateList_L(LinkList &L,int n){ //算法2.11 (后插法)创建单链表
 53     //正位序输入n个元素的值,建立到头结点的单链表L
 54     LinkList r,p;
 55     L=new LNode;
 56     L->next=NULL; //先建立一个带头结点的空链表
 57     r=L;          //尾指针r指向头结点
 58     cout<<"请输入 "<<n<<" 个数(以空格隔开,按回车结束):";
 59     for(int i=0;i<n;i++){
 60         p=new LNode;     //生成新结点
 61         cin>>p->data;      //输入元素值
 62         p->next=NULL;
 63         r->next=p;     //插入到表尾
 64         r=p;            //r指向新的尾结点   r始终指向当前节点
 65     }
 66 }//CreateList_L
 67
 68 Status findValList_L(LinkList L,int i,ElemType &indexVal){    //5.查找位序为i的元素,返回其值
 69     LinkList p=L->next;//指向第一个结点
 70     int j=1;
 71     while(p && j<i){    //找第i个节点
 72         p=p->next;
 73         ++j;
 74     }
 75     if(!p||j>i)return ERROR;//i值不合法i大于表长或者是i小于1
 76     indexVal=p->data;
 77     return OK;
 78 }
 79
 80 Status findIndexList_L(LinkList L,ElemType val,int &index){     //6.依值查找,返回其位序
 81     LinkList p=L->next;//指向第一个节点
 82     int j=1;
 83     while(p){
 84         if(p->data==val){
 85             index=j;
 86             return OK;
 87         }
 88         p=p->next;
 89         j++;
 90     }
 91     return ERROR;
 92 }
 93
 94 Status deleteIndexList_L(LinkList &L,int i){      //7.删除表中第i个元素
 95     int j=0;
 96     LinkList p=L;  //这时要指向头节点,因为当i=1时,下面的循环进不去,也就是if判断不成功,进行删除节点操作
 97     while(p && j<i-1){   //指向第i-1个节点
 98         p=p->next;
 99         j++;
100     }
101     if(!p||j>i-1)return ERROR;//如果p是空的话也就代表i大于表长,或者是
102     LinkList q=p->next;//q节点指向第i个节点
103     if(!q)return ERROR;  //根据条件,此处应该判断p的后继是否为空即为i这个特殊情况,举个例子,表长为3时,i为4,到此句的时候就成立,表示表长加1这个位置没有元素
104     p->next=q->next;//链接链表
105     delete q;
106     return OK;
107 }
108
109 Status findMaxList_L(LinkList L,int &index,int &MaxVal){    //8.返回值最大的元素及其在表中位置,引用最大值
110     if(L->next==NULL)return ERROR;//如果是空链表,则返回0
111     LinkList p=L->next->next;//将p指向第二个节点
112     int j=2;//同时同步指针位置
113     MaxVal=L->next->data;//标记第一个节点的值为最大值
114     index=1;//同步最大值的位置
115     while(p){
116         if(p->data>MaxVal){
117             MaxVal=p->data;
118             index=j;
119         }
120         p=p->next;
121         j++;
122     }
123     return OK;
124 }
125
126 Status reverseList_L(LinkList &L){   //9.就地逆置算法
127     LinkList p=L->next,q;  //先用p来保存原来的第一个节点
128     L->next=NULL;//仍利用原表的空间,此时将头结点指向空
129     if(!p)return ERROR;
130     while(p){
131         q=p->next;//先用q来保存p节点的next域,用来移动原来的链表
132         p->next=L->next; //仍用L空间,使用插在头结点后面的位置也就是前插法
133         L->next=p;   //L(带头节点)时刻指向当前节点p
134         p=q; //将p重新指向原表中后继
135     }
136     return OK;
137 }
138
139 Status delItemList_L(LinkList &L,ElemType item){   //10.删除表中所有值为item的数据元素
140     LinkList p=L,q;//指向头节点,临时指针q
141     bool f=false;//标记链表中是否有item这个元素
142     while(p){
143         if((q=p->next)&&(q->data==item)){  //先判断是否有这个p->next这个元素
144             if(!f)f=true;//有的话只标记一次就好
145             p->next=q->next;   //链接链表
146             delete q;
147         }
148         else p=p->next;//否则才移动p
149     }
150     if(!f)return ERROR;   //标记该表中没有此元素
151     return OK;
152 }
153
154 int main()
155 {
156     int i,n,choose;
157     ElemType x;
158     LinkList L,p;
159
160     choose=-1;
161     while(choose!=0)
162     {
163         cout<<"******************************************************************************\n";
164         cout<<"  1. 建立空链表;                          2. 在表中输入指定个数的数据元素\n";
165         cout<<"  3. 在第i个元素的前插入一个元素;            4. 逐个显示表中数据元素\n";
166         cout<<"  5. 查找位序为i的元素,返回其值;            6. 依值查找,返回其位序\n";
167         cout<<"  7. 删除表中第i个元素;                    8. 返回值最大的元素及其在表中位置\n";
168         cout<<"  9. 就地逆置;                            10. 删除表中所有值为item的数据元素\n";
169         cout<<"  0. 退出\n";
170         cout<<"*******************************************************************************\n";
171
172         cout<<"请选择:";
173         cin>>choose;
174         switch(choose)
175         {
176         case 1:      //建立一个单链表
177             if(InitList_L(L))
178                 cout<<"成功建立链表!\n\n";
179             break;
180         case 2:     //使用后插法创建单链表
181             cout<<"请输入一个数,代表元素的个数:";
182             cin>>n;
183             CreateList_L(L,n);
184             cout<<"成功创建链表!\n\n";
185             break;
186         case 3:  //单链表的插入
187             cout<<"请输入两个数,分别代表插入的位置和插入数值(用空格间隔,最后回车):";
188             cin>>i>>x;     //输入i和x,i代表插入的位置,x代表插入的数值
189             if(ListInsert_L(L,i,x))
190                    cout<<"成功将"<<x<<"插在第"<<i<<"个位置\n\n";
191             else
192                 cout<<"插入失败!\n\n";
193             break;
194         case 4:     //单链表的输出
195             p=L->next;//指向第一个节点
196             if(!p)
197                 cout<<"当前为空链表"<<endl<<endl;
198             else{
199                 cout<<"现在链表里的数分别是:";
200                 i=0;
201                 while(p){//循环直到为空
202                 i++;
203                 cout<<p->data<<",";
204                 p=p->next;
205                 }
206                 cout<<"共有"<<i<<"个元素。"<<endl<<endl;
207             }
208             break;
209         case 5:    //查找位序为i的元素,返回其值
210             cout<<"请输入一个你想要查找该元素的位序:";
211             cin>>i;
212             if(findValList_L(L,i,x))
213                 cout<<"位序为"<<i<<"的元素为"<<x<<".\n"<<endl;
214             else
215                 cout<<"输入位序序号不在链表节点序号范围内"<<endl<<endl;
216             break;
217         case 6:   //依值查找,返回其位序
218             int index;
219             cout<<"请输入要查找的元素:";
220             cin>>x;
221             if(findIndexList_L(L,x,index))
222                 cout<<"查找元素"<<x<<"在链表中的位序为"<<index<<".\n"<<endl;
223             else
224                 cout<<"此元素不在该链表中"<<endl<<endl;
225             break;
226         case 7:    //删除表中第i个元素
227             cout<<"请输入删除表中元素的位置:";
228             cin>>i;
229             if(deleteIndexList_L(L,i))
230                 cout<<"第"<<i<<"个位置的元素已被删除.\n"<<endl;
231             else
232                 cout<<"输入位置不在当前链表节点序号范围内"<<endl<<endl;
233             break;
234         case 8:     //返回值最大的元素及其在表中位置
235             ElemType MaxVal;
236             if(findMaxList_L(L,i,MaxVal))
237                 cout<<"当前链表中最大的元素为"<<MaxVal<<",其位置为"<<i<<".\n"<<endl;
238             else
239                 cout<<"当前为空链表"<<endl<<endl;
240             break;
241         case 9:    //就地逆置
242             if(reverseList_L(L))
243                 cout<<"就地成功逆置链表"<<endl<<endl;
244             else
245                 cout<<"此表为空链表"<<endl<<endl;
246
247             break;
248         case 10:    //删除表中所有值为item的数据元素
249             if(L->next==NULL)
250                 cout<<"当前为空链表"<<endl<<endl;
251             else{
252                 cout<<"请输入要删除链表的一个元素:";
253                 cin>>x;
254                 if(delItemList_L(L,x))
255                     cout<<"删除成功,已经将元素"<<x<<"从链表中删除.\n"<<endl;
256                 else
257                     cout<<"此链表没有"<<x<<"这个元素.\n"<<endl;
258             }
259             break;
260         }
261     }
262     return 0;
263 }

原文地址:https://www.cnblogs.com/acgoto/p/8673398.html

时间: 2024-08-30 03:24:13

实现单链表的各种基本运算的相关文章

如何使用C++实现单链表

线性表--链表 为什么假期也在发文章 //TODO NullGirlfrindException 请忽略以上两行无聊的事实...... 如何弥补顺序表的不足之处? 第一次学习线性表一定会马上接触到一种叫做顺序表(顺序存储结构),经过上一篇的分析顺序表的优缺点是很显然的,它虽然能够很快的访问读取元素,但是在解决如插入和删除等操作的时候,却需要移动大量的元素,效率较低,那么是否有一种方法可以改善或者解决这个问题呢? 首先我们需要考虑,为什么顺序表中的插入删除操作会涉及到元素的移动呢? 好家伙,问题就

数据结构实验报告-实验一 顺序表、单链表基本操作的实现

实验一    顺序表.单链表基本操作的实现   l  实验目的 1.顺序表 (1)掌握线性表的基本运算. (2)掌握顺序存储的概念,学会对顺序存储数据结构进行操作. (3)加深对顺序存储数据结构的理解,逐步培养解决实际问题的编程能力. l  实验内容 1. 顺序表 1.编写线性表基本操作函数: (1)InitList(LIST *L,int ms)初始化线性表: (2)InsertList(LIST *L,int item,int rc)向线性表的指定位置插入元素: (3)DeleteList1

数据结构之自建算法库——循环单链表

本文针对数据结构基础系列网络课程(2):线性表中第13课时双链表. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 双链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:clinklist.h,包含定义双链表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef CLINKLIST_H_INCLUDED #define CLINKLIST_H_INCLUDED //循环单链表基本运算函数 typedef int ElemT

C++ 单链表模板类实现

单链表的C语言描述 基本运算的算法--置空表.求表的长度.取结点.定位运算.插入运算.删除运算.建立不带头结点的单链表(头插入法建表).建立带头结点的单链表(尾插入法建表),输出带头结点的单链表 #include<cstdio>#include<iostream>using namespace std;template <class T>class Linklist{private: struct node { T date; node * next; node():n

单链表逆置

重写单链表逆置,熟能生巧- #include <iostream> #include <cstdlib> using namespace std; typedef struct List{ int num; struct List *next; }ListNode,*pListNode; void display(ListNode *pHead) { while(pHead) { cout<<pHead->num<<"--"; pH

02 单链表

线性表之链式存储---单链表 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 // 数据结构 6 typedef struct node 7 { 8 int data; 9 struct node *next; 10 }linkList; 11 12 // 创建单链表,并初始化 13 linkList *linkList_init(void) 14 { 15 linkList *l

(单链表)单链表的整体逆序和局部逆序

题目一:将单链表翻转. 思路:有三种方式. 一:用数组存储单链表的值,然后重新逆序赋值,效率较低. 二:利用三个指针,在原来的基础上进行逆序.这种方法比较实用,效率也高. 三:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾.需要新建一个链表,这种方法和第二种差不多. 这里我就写出第二种方法,比较实用. 代码(方法二): struct ListNode { int val; ListNode *next; ListNode(int x) :

[c语言]单链表的实现

一.基础知识:链表(线性表的链式存储结构) (1)特点:逻辑关系相邻,物理位置不一定相邻. (2)分类: a.不带头节点 b.带头节点 (3)单链表的存储结构: typedef struct SListNode {  DataType data;  struct SListNode* next; }SListNode; 二.代码实现(因避开使用二级指针,所以代码中使用了c++中的引用):此处构造的为不带头节点的链表 (1)sList.h   #pragma once typedef int Da

单链表基本操作

//头文件 #pragma once #include <stdio.h> #include <assert.h> #include <malloc.h> #include <stdlib.h> typedef int DateType; typedef struct LinkNode {  DateType _data;  struct  LinkNode* _next; } LinkNode; void PrintList(LinkNode* pHead