[数据结构与算法] (顺序)线性表简单demo程序2

main.c
 1 /*******************************************************
 2 * @: Project:    (顺序)线性表数据结构演示
 3 * @: File:        list.h
 4 * @: Function: 提供(顺序)线性表操作的数据结构定义及方法声明
 5 * @: History: 2013-09-23 21:41:19
 6 * @: Author:    Alimy
 7 *******************************************************/
 8 
 9 /*******************************************************
10 * @:头文件包含
11 *******************************************************/
12 #ifndef __SQ_LIST_H__
13 #define __SQ_LIST_H__
14 
15 /*******************************************
16 * @: 数据结构定义
17 ********************************************/
18 #define SQLIST_INIT_SIZE 100    // 线性表存储空间初始化分配单元数
19 #define SQLIST_INCREMENT_SIZE 10        // 线性表存储空间的分配增量
20 #define ElemType   signed short    int            // 此例子中的数据为有符号短整形,在VC6 中占据16bits
21 
22 #define StatusType    int        //操作状态为int类型
23 #define OK    (StatusType)1
24 #define ERROR (StatusType)0
25 
26 typedef struct{
27     ElemType * p_elemBaseAddr;    //指向存储基地址
28     int        m_currentlength;    //当前线性表的数据占用长度
29     int        m_listTotalSize;    //当前分配的存储空间总长度
30 }SqList, *pSqList;
31 
32 
33 /*******************************************
34 * @: 外部调用函数声明
35 ********************************************/
36 extern StatusType InitList_Sq(SqList* pL); //在堆中申请一个空的线性表
37 extern StatusType ListInsert_Sq(SqList* pL,int idx_location, ElemType e);// 在顺序表中插入元素
38 extern StatusType ListDelete_Sq(SqList* pL,int idx_location, ElemType* pe);//在顺序表中删除元素
39 extern int ListLocateElem_Sq(SqList* pL, ElemType e); // 定位顺序表的数据
40 extern StatusType ListDestory_Sq(SqList* pL);//销毁已经存在的顺序表
41 extern StatusType ListClear_Sq(SqList* pL); //将表置为空表
42 extern StatusType ListIsEmpty_Sq(SqList* pL);//判断顺序表是否为空表
43 extern StatusType ListGetElem_Sq(SqList* pL,int idx_location,ElemType* pe); //获取线性表中的元素
44 extern int ListGetLenth_Sq(SqList* pL);//获取表长
45 
46 extern StatusType ListPriorElem_Sq(SqList* pL,ElemType cur_e,ElemType  *pre_e); //获取某元素的前驱元素
47 extern StatusType ListNextElem_Sq(SqList* pL,ElemType cur_e,ElemType  *next_e); // 获取某元素的后继元素
48 extern void ListUnion_Sq(SqList* pLa, SqList* pLb); //两个元素取并集
49 extern void DisplayList_Sq(SqList * pL); // 打印当前的顺序表所有元素
50 
51 
52 #endif // end of __SQ_LIST_H__
sq_list.h
  1 /*******************************************************
  2 * @: Project:    (顺序)线性表数据结构演示
  3 * @: File:        sq_list.c
  4 * @: Function: 提供(顺序)线性表操作的基本函数和方法
  5 * @: History:    2013-09-23 21:44:02
  6 * @: Author:    Alimy
  7 *******************************************************/
  8 
  9 /*******************************************************
 10 * @: 头文件包含 
 11 *******************************************************/
 12 #include "sq_list.h"
 13 #include <stdio.h> 
 14 #include <conio.h>
 15 
 16 
 17 /*******************************************************
 18 * @: (外部&内部)变量声明及定义
 19 *******************************************************/
 20 
 21 /*******************************************************
 22 * @: (外部&内部)函数声明及定义
 23 *******************************************************/
 24 StatusType InitList_Sq(SqList* pL); //在堆中申请一个空的线性表
 25 StatusType ListInsert_Sq(SqList* pL,int idx_location, ElemType e);// 在顺序表中插入元素
 26 StatusType ListDelete_Sq(SqList* pL,int idx_location, ElemType* pe);//在顺序表中删除元素
 27 int ListLocateElem_Sq(SqList* pL, ElemType e);//在顺序表中定位元素
 28 StatusType ListDestory_Sq(SqList* pL);//销毁已经存在的线性表
 29 StatusType ListClear_Sq(SqList* pL); //将表置为空表
 30 StatusType ListIsEmpty_Sq(SqList * pL);//判断顺序表是否为空表
 31 StatusType ListGetElem_Sq(SqList* pL,int idx_location,ElemType* pe); //获取线性表中的元素
 32 int ListGetLenth_Sq(SqList* pL);//获取表长
 33 void DisplayList_Sq(SqList* pL);
 34 
 35 /*******************************************************
 36 * @: 内部函数具体实现
 37 *******************************************************/
 38 
 39 /*
 40 * @:动态申请堆中空间作为存储空间
 41 * @: 返回值
 42 * @:        申请成功 返回OK
 43 * @:        申请失败返回ERROR
 44 */
 45 StatusType InitList_Sq(SqList* pL){
 46 //    int idx = 0;
 47 
 48     if(pL->p_elemBaseAddr != NULL){  //可能造成先前申请的堆空间的丢失
 49         printf("顺序表已经被初始化过了,不需要再次初始化\n");
 50         return ERROR;
 51     }
 52 
 53     pL->p_elemBaseAddr = (ElemType*)(malloc(SQLIST_INIT_SIZE*sizeof(ElemType))); //尝试在堆中申请空间
 54     if(pL->p_elemBaseAddr == NULL){    //初始化空间 申请失败
 55         printf("初始化空间失败,无法在堆中申请初始化空间");
 56         return ERROR;
 57     }
 58 //    pL->p_elemBaseAddr = pL->p_elemBaseAddr; //此步骤已经做过
 59     pL->m_currentlength = 0; //当前为空表,所以表长为0
 60     pL->m_listTotalSize = SQLIST_INIT_SIZE; // 总空间长度为初始化长度
 61     printf("顺序表初始化完成,当前表长为 【%d】, 总空间长度为 【%d】 \n",pL->m_currentlength,pL->m_listTotalSize);
 62     printf("按任意键进入主菜单 \n");
 63     getch();
 64 //    printf("在堆中初始化顺序表成功,堆中的数据是: \n");
 65 //    for(idx = 0; idx<pL->m_listTotalSize;idx++){
 66 //        printf("pL->p_elemBaseAddr[%d] = %d \n",idx+1,pL->p_elemBaseAddr[idx]);
 67 //        }
 68     return OK;
 69 }
 70 
 71 /*
 72 * @:在pL 指向的顺序表中的第idx_location位置中插入值为e的元素
 73 * @: 返回值
 74 * @:        插入成功 返回OK
 75 * @:        插入失败 返回ERROR
 76 */
 77 
 78 StatusType ListInsert_Sq(SqList* pL,int idx_location, ElemType e){
 79     ElemType*  newBaseAddr = NULL;
 80     ElemType*  p_WorkHead = NULL; //头 工作指针
 81     ElemType*  p_WorkTail = NULL;     //尾工作指针
 82     if((idx_location<1)||(idx_location>pL->m_currentlength+1)){
 83         printf("位置idx_location = 【%d】 值非法,插入元素操作失败 \n",idx_location);
 84         return ERROR;        // 位置idx_location 值非法
 85     }
 86 
 87     if(pL->m_currentlength == pL->m_listTotalSize){  //若表已经满了,就需要继续在堆中申请空间
 88         newBaseAddr = (ElemType*)realloc(pL->p_elemBaseAddr,(pL->m_currentlength+SQLIST_INCREMENT_SIZE)*sizeof(ElemType));
 89         if(newBaseAddr == NULL){//申请空间失败
 90             printf("当前顺序表已经满了,且尝试在堆中申请新的空间失败,插入操作失败 \n");
 91             return ERROR;
 92         }else{ // 申请成功
 93         
 94             pL->p_elemBaseAddr = newBaseAddr;  // 修正顺序表参数
 95             pL->m_listTotalSize += SQLIST_INCREMENT_SIZE;
 96         }
 97     }
 98 
 99 
100     //空间已经足够
101     p_WorkHead = &pL->p_elemBaseAddr[idx_location-1]; // p_work = pL->elemBaseAddr + idx_location -1;
102     p_WorkTail = &pL->p_elemBaseAddr[pL->m_listTotalSize-1]; // 
103 
104     for(;p_WorkHead<=p_WorkTail;p_WorkTail--){  // 只要头工作指针不小于尾工作指针,就要做后移操作
105         *(p_WorkTail+1) = *(p_WorkTail);  
106     }
107 
108     *p_WorkHead = e; // 填入数据
109     pL->m_currentlength += 1;  // 修正参数
110     printf("顺序表元素插入操作完成成功,元素被插入的位置为[%d],元素的值为[%d] \n",idx_location,e);
111     return OK;    
112 }
113 
114 /*
115 * @:删除pL 指向的顺序表中的第idx_location位置的元素,并且将被删除的元素的值赋值给pe指向的内存空间
116 * @: 返回值
117 * @:        删除    成功 返回OK
118 * @:        删除失败 返回ERROR
119 */
120 
121 StatusType ListDelete_Sq(SqList* pL,int idx_location, ElemType* pe){
122 
123     ElemType*  p_WorkHead = NULL; //头 工作指针
124     ElemType*  p_WorkTail = NULL;     //尾工作指针
125     if(pL->m_currentlength == 0){
126         printf("当前顺序表为空表,无法执行元素删除操作 \n");
127         return OK;
128     }
129     if((idx_location<1)||(idx_location>pL->m_currentlength)){ // 1 <= idx_location 且idx_location <= pL->m_currentlength 才是合法范围
130         printf("【删除位置 idx_location 有误,请检查数据输入 】\n");
131         printf("----调试信息输出----\n");
132         printf("【当前顺序表的表长为 %d 】\n【要删除的元素索引为 %d 】\n ",pL->m_currentlength,idx_location);        
133         printf("----调试信息输出----\n");
134         return  ERROR;
135     }
136 
137 
138     p_WorkHead = &pL->p_elemBaseAddr[idx_location - 1];
139     p_WorkTail = &pL->p_elemBaseAddr[pL->m_currentlength-1];
140 
141     *pe =  *p_WorkHead; // 保存值
142         
143     for(;p_WorkHead<p_WorkTail;p_WorkHead++){
144         *(p_WorkHead) = *(p_WorkHead+1);  //向左搬移
145     }
146 
147     pL->m_currentlength -= 1;  //删除了一个元素
148     printf("删除顺序表元素成功,被删除的元素的值为 %d \n",*pe);
149     return OK;
150     
151 
152 }
153 
154 /*
155 *@: 在pL指向的顺序表中定位值为e的元素.
156 *@:返回值: 
157 *@:        若在pL指向的顺序表中不存在值为e的元素,则返回【0】
158 *@:        若在pL指向的顺序表中至少存在一个值为e的元素,则返回值为e的元素的最小索引。
159 */
160 int ListLocateElem_Sq(SqList* pL, ElemType e){ 
161     int idx ;
162     for(idx=1;idx<=pL->m_currentlength;idx++){
163         if(e == pL->p_elemBaseAddr[idx-1]){ // compare函数即 == 号 ,不同的ElemType类型是compare函数具有多样性,例如ElemType为数组型的时候,compare函数就不能这么写了
164             printf("在顺序表中找到至少一个值为【%d】的元素,元素最小索引为【%d】\n",e,idx);
165             return idx;
166         }
167     }
168 
169     //遍历所有顺序表的当前元素,没有找到值为e的元素
170     printf("在当前顺序表中没有找到值为【%d】的元素\n",e);
171     return 0;
172 }
173 
174 /*
175 *@: 销毁已经存在的顺序表
176 *@:返回值: 
177 *@:        销毁成功返回OK
178 *@:        销毁失败返回ERROR
179 */
180 
181 StatusType ListDestory_Sq(SqList* pL){
182     if(pL->p_elemBaseAddr == NULL){//本来就是空表
183         printf("当前顺序表本来就是空表,无法进行销毁操作 \n");
184         return ERROR;
185     }
186 
187     free(pL->p_elemBaseAddr);
188     pL->p_elemBaseAddr = NULL;
189     pL->m_currentlength = 0;
190     pL->m_listTotalSize = 0;
191     printf("销毁顺序表成功\n");
192     return OK;
193 }
194 
195 /*
196 *@: 清除顺序表
197 *@:返回值: 
198 *@:        清除成功返回OK
199 *@:        清除失败返回ERROR
200 */
201 StatusType ListClear_Sq(SqList* pL){ //将表置为空表
202     if((pL->m_currentlength==0)&&(pL->m_listTotalSize==0)&&(pL->p_elemBaseAddr==NULL)){
203         printf("当前顺序表未被初始化,无法执行清除操作\n");
204         return ERROR;
205     }
206 
207     //pL->p_elemBaseAddr = pL->p_elemBaseAddr; //基址不变
208     pL->m_currentlength = 0;  //设置为空表
209     //pL->m_listTotalSize = pL->m_listTotalSize;//总空间不变
210     return OK;
211 }
212 
213 /*
214 *@: 判断顺序表是否为空表
215 *@:返回值: 
216 *@:     顺序表未被初始化或者顺序表不为空表返回ERROR
217 *@:    顺序表存在且表为空表返回OK
218 */
219 
220 StatusType ListIsEmpty_Sq(SqList * pL){//判断顺序表是否为空表
221     if((pL->m_currentlength==0)&&(pL->m_listTotalSize==0)&&(pL->p_elemBaseAddr==NULL)){
222         printf("当前顺序表未被初始化,请确认顺序表已经被分配空间\n");
223         return ERROR;
224     }
225 
226     if(pL->m_currentlength != 0){   //ListGetCurrentLength_Sq
227         printf("当前顺序表存在,且不为空表");
228         return ERROR;
229     }
230     else{
231         printf("当前顺序表存在,且为空表");
232         return OK;
233     }
234 
235 
236 }
237 
238 /*
239 *@: 获取pL 指向的线性表中的第idx_location 个元素,并将该元素的值赋值给pe指向的内存空间
240 *@:返回值: 
241 *@:     获取元素成功返回OK
242 *@:    获取元素失败返回ERROR
243 */
244 StatusType ListGetElem_Sq(SqList* pL,int idx_location,ElemType* pe){
245     if(pL->p_elemBaseAddr == NULL){
246         printf("当前表未被初始化。无法执行获取元素操作 \n");
247         return ERROR;
248     }
249 
250     if((idx_location<1)||(idx_location>pL->m_currentlength)){  //位置索引有误
251         printf("需要获取元素的索引有误,请检查是否符合要求\n");
252         printf("当前顺序表的 当前长度为 【%d】,要求获取的元素的索引为【%d】\n",pL->m_currentlength,idx_location);
253         return ERROR;
254     }
255 
256     *pe = pL->p_elemBaseAddr[idx_location-1];//赋值
257     return OK;
258 
259 
260 }
261 
262 
263 /*
264 *@: 获取pL 指向的线性表的当前表长(当pL指向非NULL时)
265 *@:返回值: 
266 *@:     当前表长----返回非0
267 *@:    pL指向为NULL或者基址指向为NULL(空表或者pL未被初始化) ---返回0
268 */
269 
270 int ListGetLenth_Sq(SqList* pL){
271     if((pL == NULL)||(pL->p_elemBaseAddr == NULL)){
272         printf("表为空表或者表未被初始化 ,无法获取表长 \n");
273         return 0;
274     }
275      return(pL->m_currentlength);
276 }
277 
278 
279 
280 /*
281 * @:打印pL指向的顺序表中的所有元素
282 * @: 返回值(无)
283 */
284 void DisplayList_Sq(SqList* pL){
285     int idx = 0;
286     if(pL->m_currentlength == 0){
287         printf("当前表为空表,打印不出东东 \n");
288     }
289     else{
290         printf("当前顺序表共有 %d个元素,依次打印如下 \n",pL->m_currentlength);
291         for(idx = 0; idx < pL->m_currentlength;idx++){
292             printf("第 %d 个元素的值为 %d \n",idx+1,pL->p_elemBaseAddr[idx]);
293         }
294 
295         printf("打印完毕! \n");
296     }
297     return;
298 }
299 
300 
301 
302 //演示未用到的函数
303 
304 StatusType ListPriorElem_Sq(SqList* pL,ElemType cur_e,ElemType  *pre_e); //获取某元素的前驱元素
305 StatusType ListNextElem_Sq(SqList* pL,ElemType cur_e,ElemType  *next_e); // 获取某元素的后继元素
306 void ListUnion_Sq(SqList* pLa, SqList* pLb); //两个线性表取并集
307 void MergeList_Sq(SqList* pLa, SqList* pLb, SqList *pLc); // 归并非递减排列的顺序表la 和 lb到非递减排列的顺序表 lc中
308 
309 
310 /*
311 *@:获取pL指向的顺序表中值为cur_e 的元素的前驱元素,并将前驱元素的值赋值给pre_e 指向的内存空间
312 *@:返回值
313 *@:     取前驱元素成功---返回OK
314 *@:    取前驱元素失败---返回ERROR
315 */
316 
317 StatusType ListPriorElem_Sq(SqList* pL,ElemType cur_e,ElemType  *pre_e){
318     int idx_current = 0;
319     idx_current = ListLocateElem_Sq(pL,cur_e);
320     if(0 == idx_current ){
321         printf("当前线性表中没有值为【%d】的元素,获取前驱元素失败",cur_e);
322         return ERROR;
323     }
324 
325     if(1 == idx_current){
326         printf("值为【%d】的元素是该线性表的第一个元素,根据线性表的定义,第一个元素无前驱元素,获取前驱元素失败",cur_e);
327         return ERROR;
328     }
329 
330     *pre_e = pL->p_elemBaseAddr[idx_current-1-1];  //获取前驱元素
331     return OK;
332 
333 }
334 
335 /*
336 *@:获取pL指向的顺序表中值为cur_e 的元素的后继元素,并将后继元素的值赋值给next_e 指向的内存空间
337 *@:返回值
338 *@:     取后继元素成功---返回OK
339 *@:    取后继元素失败---返回ERROR
340 */
341 
342 StatusType ListNextElem_Sq(SqList* pL,ElemType cur_e,ElemType  *next_e){
343     int idx_current = 0;
344     idx_current = ListLocateElem_Sq(pL,cur_e);
345 
346     if(0 == idx_current){
347         printf("当前线性表中没有值为【%d】的元素,获取后继元素失败",cur_e);
348         return ERROR;
349     }
350 
351     if(pL->m_currentlength == idx_current){
352         printf("值为【%d】的元素是该线性表的最后一个元素,根据线性表的定义,最后一个元素无后继元素,获取后继元素失败",cur_e);
353         return ERROR;
354     }
355 
356     *next_e = pL->p_elemBaseAddr[idx_current-1+1];
357     return OK;
358 }
359 
360 
361 /*
362 *@: 将所有存在于Lb且不存在于pLa中的元素插入到 La的表尾(先行条件La 和Lb都已经被初始化过了)
363 */
364 void ListUnion_Sq(SqList* pLa, SqList* pLb){ //两个线性表取并集
365 
366     int Lb_Len = ListGetLenth_Sq(pLb); 
367     int La_Len = ListGetLenth_Sq(pLb);
368     int idx_location = 0;
369     ElemType e = 0;
370     for(idx_location = 0+1;idx_location < Lb_Len+1;idx_location++){
371         ListGetElem_Sq(pLb,idx_location,&e);
372         if(0 == ListLocateElem_Sq(pLa,e)){ //La  中无值为e的元素
373             La_Len += 1;//准备插入,增加表的长度
374             ListInsert_Sq(pLa,La_Len,e);
375         }
376     }
377 }
378 
379 /*
380 *@:已知线性表La和Lb中的数据元素按值非递减排列
381 *@:归并La和Lb得到新的线性表Lc,Lc中的数据元素也按值非递减排列
382 */
383 void MergeList_Sq(SqList* pLa, SqList* pLb, SqList *pLc){
384     int idx1 = 1,idx2 = 1;
385     int La_Len = ListGetLenth_Sq(pLa);
386     int Lb_Len = ListGetLenth_Sq(pLb);
387     int Lc_Len = 0;
388     
389     ElemType e1 = 0;
390     ElemType e2 = 0;
391     InitList_Sq(pLc);
392     
393     while((idx1<=La_Len)&&(idx2<=Lb_Len)){ // La & Lb 都还有更大元素
394         ListGetElem_Sq(pLa,idx1,&e1);    
395         ListGetElem_Sq(pLb,idx2,&e2); //获取更不小元素
396         
397         if(e1<=e2){ //小的先插入Lc中去
398             idx1++;   // 准备取La中的更不小元素去
399             Lc_Len++;    //准备插入Lc
400             ListInsert_Sq(pLc,Lc_Len,e1);
401         }
402         else{
403             idx2++;   // 准备取Lb中的更不小元素去
404             Lc_Len++;    //准备插入Lc
405             ListInsert_Sq(pLc,Lc_Len,e2);
406         }    
407     
408     }
409     
410     while(idx1<=La_Len){  //Lb先到头
411         idx1++;
412         Lc_Len++;
413         ListGetElem_Sq(pLa,idx1,&e1);
414         ListInsert_Sq(pLc,Lc_Len,e1);
415     }
416     
417     while(idx2<=Lb_Len){  //La先到头
418         idx2++;
419         Lc_Len++;
420         ListGetElem_Sq(pLb,idx2,&e2);
421         ListInsert_Sq(pLc,Lc_Len,e2);
422     }
423     
424 }
sq_list.c

 

posted @ 2013-10-06 14:18  Alimy  阅读(248)  评论(0)    收藏  举报