码迷,mamicode.com
首页 > 其他好文 > 详细

链表不带头结点的实现

时间:2015-04-16 19:37:29      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:

首先要强调的是,ADT没有变化,只是实现上的变化。

不带头结点的实现比带头结点的实现稍微复杂一些,尤其体现在插入(第58-60行)和删除(第88-91行),要单独处理表头改变的情况。而带头结点的链表表头不会变化,总是指向头结点。

其他操作的不同之处同学们自行比较。

下面的问题会帮助你的理解:

 第83行 while(p && j < i - 1) {   而教材上带头结点的实现为while(p->next && j < i - 1) {

为什么会有这种区别?

点击看答案
技术分享
不带头结点的方式不能保证p不为空,p->next自然可能产生问题。
带头结点的实现可以保证这一点。

另外,书上采用p->next的动机也非常明显,不仅要找到第i-1个结点(循环结束后的p指向的结点), 而且要保证第i个结点(即p->next)也存在。

所以不带头结点的方式第87行才有下面的代码
if(!p || !p->next || i < 1) 
View Code

 

 

 

  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     ElemType data;                            //结点的数据域
 12     struct LNode *next;                        //结点的指针域
 13 } LNode, *LinkList;                            //LinkList为指向结构体LNode的指针类型
 14 
 15 
 16 Status InitList_L(LinkList &L)                 //算法2.5 单链表的初始化
 17 {
 18     //构造一个空的单链表L
 19     L = NULL;
 20     return OK;
 21 }
 22 
 23 Status GetElem_L(LinkList L, int i, ElemType &e)         //算法2.6 按序号查找
 24 {
 25     //在带头结点的单链表L中查找第i个元素
 26     int j;
 27     LNode *p;
 28     p = L;
 29     j = 1;                            //初始化,p指向第一个结点,j为计数器
 30     while(j < i && p) {                            //顺链域向后扫描,直到p指向第i个元素或p为空
 31         p = p->next;
 32         ++j;
 33     }
 34     if(!p || j > i)    return ERROR;            //第i个元素不存在
 35     e = p->data;                                //取第i个元素
 36     return OK;
 37 }                                            //GetElem_L
 38 
 39 LNode *LocateElem_L(LinkList L, ElemType e)             //算法2.7 按值查找
 40 {
 41     //在带头结点的单链表L中查找值为e的元素
 42     LNode *p;
 43     p = L;
 44     while(p && p->data != e)
 45         p = p->next;                            //寻找满足条件的结点
 46     return p;                                //返回L中的值为e的数据元素的位置,查找失败返回NULL
 47 }                                            //LocateElem_L
 48 
 49 Status ListInsert_L(LinkList &L, int i, ElemType &e)         //算法2.8 单链表的插入
 50 {
 51     //在带头结点的单链表L中第i个位置之前插入元素e
 52     int j;
 53     LNode *p, *s;
 54     p = L;
 55     j = 1; //与教材不同之处
 56     s = new LNode;                            //生成新结点s
 57     s->data = e;                                //将结点s的数据域置为e
 58     if(i == 1) { //插在表头
 59         s->next = L;
 60         L = s; //修改表头
 61     } else {
 62         while(p && j < i - 1) {
 63             p = p->next;    //寻找第i-1个结点
 64             ++j;
 65         }
 66         if(!p || j > i - 1) {
 67             delete s;
 68             return ERROR;            //i大于表长+1或者小于1
 69         }
 70         s->next = p->next;                        //将结点s插入L中
 71         p->next = s;
 72     }
 73     return OK;
 74 }                                            //ListInsert_L
 75 
 76 Status ListDelete_L(LinkList &L, int i, ElemType &e)         //算法2.9 单链表的删除
 77 {
 78     //在带头结点的单链表L中,删除第i个位置,并由e返回值
 79     LNode *p, *q;
 80     int j;
 81     p = L;
 82     j = 1;
 83     while(p && j < i - 1) {
 84         p = p->next;    //寻找第i-1个结点
 85         ++j;
 86     }
 87     if(!p || !p->next || i < 1)        return ERROR;    //i大于表长或者小于1, p->next==NULL为表长加一情形
 88     if(i == 1) { //删除表头
 89         e = p->data;
 90         L = p->next;
 91         delete p;
 92     } else {
 93         q = p->next;                                    //临时保存被删结点的地址以备释放
 94         p->next = q->next;                            //改变删除结点前驱结点的指针域
 95         e = q->data;                                    //保存删除结点的数据域
 96         delete q;                                    //释放删除结点的空间
 97     }
 98     return OK;
 99 }                                                //ListDelete_L
100 
101 
102 void CreateList_L(LinkList &L, int n)                 //算法2.11 后插法创建单链表
103 {
104     //正位序输入n个元素的值,建立到头结点的单链表L
105     LNode *r, *p;
106     L = NULL;                                //先建立一个带头结点的空链表
107     cout << "请输入 " << n << " 个数:\n";
108     for(int i = 0; i < n; i++) {
109         p = new LNode;                            //生成新结点
110         cin >> p->data;                            //输入元素值
111         p->next = NULL;
112         if(i == 0) { //第一个结点,表头
113             r = L = p;
114         } else {
115             r->next = p;                    //插入到表尾
116             r = p;                                    //r指向新的尾结点
117         }
118     }
119 }                                                //CreateList_L
120 
121 int main()
122 {
123     int res, a, b, choose;
124     LNode *L, *p;
125     cout << "1. 建立链表\n";
126     cout << "2. 输入数据\n";
127     cout << "3. 按位置查找\n";
128     cout << "4. 按值查找\n";
129     cout << "5. 链表的插入\n";
130     cout << "6. 链表的删除\n";
131     cout << "7. 输出数据\n";
132     cout << "0. 退出\n\n";
133 
134     choose = -1;
135     while(choose != 0) {
136         cout << "请选择:";
137         cin >> choose;
138         switch(choose) {
139         case 1:                    //建立一个单链表
140             if(InitList_L(L))
141                 cout << "成功建立链表!\n\n";
142             break;
143         case 2:                    //使用后插法创建单链表
144             CreateList_L(L, 4);
145             cout << "成功创建链表!\n\n";
146             break;
147         case 3:                    //单链表的按序号查找
148             cout << "请输入一个位置用来查找:";
149             cin >> a;
150             if(GetElem_L(L, a, res))
151                 cout << "查找成功!第" << a << "个数是:" << res << "\n\n";
152             else
153                 cout << "查找失败\n\n";
154             break;
155         case 4:                    //单链表的按值查找
156             cout << "请输入一个数值用来查找:";
157             cin >> b;
158             if(LocateElem_L(L, b) != NULL)
159                 cout << "查找成功\n\n";
160             else
161                 cout << "查找失败! " << b << " 没有找到\n\n";
162             break;
163         case 5:                    //单链表的插入
164             cout << "请输入两个数分别代表插入的位置和数值:";
165             cin >> a >> b;
166             if(ListInsert_L(L, a, b))
167                 cout << "成功将" << b << "插在第" << a << "个位置\n\n";
168             else
169                 cout << "插入失败!\n\n";
170             break;
171         case 6:                    //单链表的删除
172             cout << "请输入一个位置用来删除:";
173             cin >> a;
174             if(ListDelete_L(L, a, res))
175                 cout << "删除成功!被删除的数是:" << res << "\n\n";
176             else
177                 cout << "删除失败!\n\n";
178             break;
179         case 7:                    //单链表的输出
180             cout << "现在链表里的数分别是:\n";
181             p = L;
182             while(p) {
183                 cout << p->data << " ";
184                 p = p->next;
185             }
186             cout << endl;
187             break;
188         }
189     }
190     return 0;
191 }

 

链表不带头结点的实现

标签:

原文地址:http://www.cnblogs.com/4bytes/p/4432816.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!