数据结构——单链表(带头结点和不带头结点)

  1 //单链表:通过各结点的链接指针来表示结点间的逻辑关系,长度可扩充,遍历或查找
  2 //只能从指针的指示的首元结点开始,跟随链接指针逐个结点进行访问,进行删除或插
  3 //入时,只需修改相关结点的指针域,但链接表比顺序表需要的存储空间多
  4 
  5 
  6 //单链表的结构定义
  7 typedef int DataType;
  8 typedef struct node
  9 {
 10     DataType data;//链表结点
 11     struct node* link;//数据域
 12 }LinkNode, *LinkList;//链接指针域
 13 
//头指针,包含0个或多个结点空表为0个结点
 14 //单链表中的插入与删除
 15 //单链表插入算法
 16 int Insert(LinkList& first, int i, DataType x)
 17 {
 18     //将新元素x插入到第i个结点位置,i从1开始,i=1表示插入到原首元结点之前
 19     if(!first || i==1)//插入到空表或非空表首元结点前
 20     {
 21         LinkNode *newNode = new LinkNode;//建立一个新结点
 22         if(!newNode)
 23         {
 24             cerr<<"存储分配错误!\n";
 25             exit(1);
 26         }
 27         newNode->data = x;
 28         newNode->link = first;//新结点成为第一个结点
 29         first = newNode;
 30     }
 31     else//插入到链中间或尾部
 32     {
 33         LinkNode *p = first;//从第一个结点开始检测
 34         int k = 1;
 35         while(p != NULL && k<i-1)//循环找第i-1个结点
 36         {
 37             p = p->link;
 38             k++;
 39         }
 40         if(p == NULL && first)//非空表且链太短
 41         {
 42             cerr<<"无效的插入位置!"<<endl;
 43             return 0;
 44         }
 45         else
 46         {
 47             LinkNode *newNode = new LinkNode;//建立一个新结点
 48             if(!newNode)
 49             {
 50                 cerr<<"存储分配错误!"<<endl;
 51                 exit(1);
 52             }
 53             newNode->data = x;
 54             newNode->link = p->link;
 55             p->link = newNode;
 56         }
 57     }
 58     return 1;//正常插入
 59 }
 60 
 61 //单链表删除算法
 62 int Remove(LinkList& first, int i, DataType& x)
 63 {
 64     //将链表中的第i个元素删去,i从1开始,引用型参数x返回被删元素的值
 65     LinkNode *q, *p;
 66     int k;
 67     if(i<=1)//删除首元结点时表头退到下一个结点
 68     {
 69         q = first;
 70         first = first->link;
 71     }
 72     else
 73     {
 74         p = first;
 75         k = 1;
 76         while(p != NULL && k<i-1)//循链找第i-1号结点
 77         {
 78             p=p->link;
 79             k++;
 80         }
 81         if(p == NULL || p->link == NULL)//空表或者链太短只有头结点
 82         {
 83             cerr<<"无效的删除位置!\n";
 84             return 0;
 85         }
 86         q = p->link;//保存第i号结点的地址
 87         p->link = q->link;//第i-1号结点与第i+1号结点链接
 88     }
 89     x = q->data;//取出被删除结点中的数据值
 90     delete q;//并删除
 91     return 1;
 92 }
 
 97带头结点,头结点data域不存储任何信息空表为头结点
//带头结点的单链表
 98 //头结点的data域不存储任何信息。把头结点当第0个结点,带头结点的单链表
 99 //简化了链表的插入与删除操作代码的实现
100 
101 //初始化单链表
102 void initList(LinkList &first)
103 {   
104     first =new LinkNode;//创建头结点
105     if(!first)
106     {   
107         cerr<<"存储分配失败!\n";
108         exit(1);
109     }
110     first->link = NULL;//置空
111 }
112 
113 //清空单链表
114 void clearList(LinkList &first)
115 {   
116     LinkNode *q;
117     while(first->link != NULL)//当链不空时,删去链中的所有结点
118     {
119         q = first->link;
120         first->link = q->link;//保存被删结点,从链上摘下该结点
121         delete q;//删除(仅留一个头结点)
122     }
123 }
124 
125 //计算表的长度
126 int Length(LinkList &first)
127 {
128     LinkNode *p = first->link;
129     int count = 0;
130     while(p != NULL)//循链扫描,计算结点数
131     {
132         p = p->link;
133         count++;
134     }
135     return count;
136 }
137 
138 //判断单链表是否为空。如果表空,则函数返回1,否则函数返回0
139 int isEmpty(LinkList &first)
140 {
141     return (first->link == NULL);
142 }
143 
144 //在单链表中查找与x匹配的元素,查找成功时函数返回该结点地址,否则返回NULL值
145 LinkNode* Search(LinkList& first, DataType x)
146 {
147     LinkNode *p = first->link;
148     while(p != NULL && p->data != x)//循链逐个找含x的结点
149         p = p->link;
150     return p; //返回指针p的内容(地址)
151 }
152 
153 //在单链表中对第i(0<=i)个结点定位。函数返回表中第i个结点的地址
154 //若i<0或i超出表中结点个数,则返回NULL
155 LinkNode* Locate(LinkList& first, int i)
156 {
157     if(i<0)//找头结点时,i<0不合理
158         return NULL;
159     LinkNode *p = first;
160     int k = 0;
161     while(p != NULL && k<i)//循链找第i个结点,k做结点计数
162     {
163         p = p->link;
164         k++;
165     }
166     return p;//返回NULL,表示i值太大,返回结点地址
167 }
168 
169 //将新元素x插入在表中第i(1<=i)个结点位置。如i不合理则函数返回0,否则函数返回1
170 int Insert(LinkList& first, int i, DataType x)
171 {
172     LinkNode *p = Locate(first, i-1);//定位于第i-1个结点
173     if(p == NULL)//i不合理,插入不成功
174         return 0;
175     LinkNode *s = new LinkNode;//创建一个新结点
176     if(!s)
177     {
178         cerr<<"存储分配错误\n";
179         exit(1);
180     }
181     s->data = x;
182     s->link = p->link;//将*s链接在*p之后
183     p->link = s;//插入成功
184     return 1;
185 }
186 
187 //将链表中的第i个元素删去,通过引用型参数x返回该元素的值
188 //如果i不合理则函数返回0,否则返回1
189 int Remove(LinkList& first, int i, DataType& x)
190 {
191     LinkNode *p = Locate(first, i-1);//定位于i-1第个结点
192     if(p == NULL || p->link == NULL)
193         return 0;
194     LinkNode *q = p->link;//用q保存被删结点地址
195     p->link = q->link;//重新链接,将被删结点从链中摘下
196     x = q->data;//取出被删结点中的数据
197     delete q;//释放结点
198     return 1;//删除成功
199 }
200 
201 //函数假定链表first1已存在且为空,即first1的头结点已创建且
202 //first1->link == NULL
203 //复制链表first2的全部结点到空链表first1
204 void Copy(LinkList& first1, LinkList& first2)
205 {
206     LinkNode *srcptr = first2->link;//srcptr是源链指针
207     LinkNode *destptr = first1;//destptr是目标链尾指针
208     while(srcptr->link != NULL)//逐个结点复制
209     {
210         destptr->link = new LinkNode;//新结点链入目标链尾
211         if(!destptr)
212         {
213             cerr<<"存储分配失败!\n";
214             exit(1);
215         }
216         destptr = destptr->link;
217         destptr->data = srcptr->data;//结点数据传送
218         srcptr = srcptr->link;//传送源链下一结点数据
219     }
220     destptr->link = NULL;//目标链收尾
221 }
222 

223 



224 //实例,一个非空链表first,在first中正向输出所有结点的值,其递归算法为:
225 //正向输出链表各结点值的递归算法
226 void write(LinkNode *first)
227 {
228     if(first == NULL)//递归到底,空表返回
229         return;
230     cout<<first->data<<endl;//输出当前结点的值
231     write(first->link);//以下一个结点为表头继续递归输出
232 }
233 //正向输出非递归算法
234 void write(LinkNode *first)//非递归(迭代)算法
235 {
236     while(first->link != NULL)//循环输出到链空
237     {
238         cout<< first->link->data <<endl;//链表非空,输出结点数据
239         first = first->link;//继续输出下一结点
240     }
241 }


 

245 //尾插法创建单链表
246 void insertRear(LinkList& first, LinkNode* & last, DataType endTag)
247 {
248 //endTag是约定的输入序列结束标志,如果输入序列是正整数,endTag可以是0或负数
249 //如果输入序列是字符,engTag可以是字符集中不会出现的字符,入"\0".
250      DataType val;
251      cin>>val;
252      if(val == endTag)//链表收尾,停止创建
253          last->link = NULL;
254      else
255      {
256          last = new LinkNode;//创建新结点
257          if(!last)
258          {
259              cerr<<"存储分配错误!\n";
260              exit(1);
261          }
262          last->data = val;//last结点赋值
263          insertRear(first, last->link, endTag);//递归创建后续链表
264      }
265 }
266 void main(void)
267 {
268     LinkList *L = new LinkNode;
269     if(!L)
270     {cerr<<"内存分配错误!\n"; exit(1);}
271     cin>>L->data;
272     LinkNode *rear = L;
273     insertRear(L, rear->link, L->data);
274 }
275 
276 
277 

278 //前插法创建一个单链表
279 void insertFront(LinkList& first, DataType endTag)
280 {
281     DataType val;
282     cin>>val;
283     if(val == endTag)//链表数据输入结束,停止创建
284         return;
285     LinkNode *s = new LinkNode;//创建新结点
286     if(!s)
287     {cerr<<"存储分配错误\n"; exit(1);}
288     s->data = val;//s结点赋值
289     s->link = first->link;//作为首元结点
290     first->link = s;//链入头结点之后
291     insertFront(first, endTag);//递归创建链表
292 }
293 void main(void)
294 {
295     LinkList *L = new LinkNode;
296     if(!L)
297     {cerr<<"存储分配错误\n"; exit(1);}
298     cin>>L->data;//输入约定的输入序列结束标志
299     L->link = NULL;//链表置空
300     insertFront(L, L->data);//递归建立单链表
301 }


猜你喜欢

转载自blog.csdn.net/csdn_wanziooo/article/details/77907933