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

线性表的顺序存储

时间:2015-03-13 10:41:13      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:

 线性表的顺序存储,其数据结构以及具体实现详见下面代码,重要知识点全部以注释的形式在代码中展示出来。

  1 /***
  2 线性表的顺序存储结构是一种 随机存取 的存储结构
  3 在线性顺序表中插入或者删除一个元素,时间都消耗在移动元素上,平均约移动一般的元素,
  4 故ListInsert和ListDelete的时间复杂度都为O(n);
  5 */
  6 #include<stdio.h>
  7 #include<stdlib.h>
  8 //***************线性表的动态分配顺序存储结构*****************
  9 #define LIST_INIT_SIZE 100  //线性表存储空间的初始分配量
 10 #define LISTINCREMENT  10   //线性表存储空间的存储增量
 11 typedef struct
 12 {
 13     int *elem;   //数组指针,存储空间基址
 14     int length;  //当前长度
 15     int listsize;//当前分配的存储容量(以sizeof(int)为单位)
 16 }SqList;
 17 
 18 //******************初始化线性表,构造一个空表********************
 19 void InitList(SqList &L)
 20 {
 21     L.elem = (int *)malloc(LIST_INIT_SIZE * sizeof(int));
 22     if (!L.elem)
 23     {
 24         printf("存储分配失败,任意键退出!\n");
 25         getchar();
 26         exit(1);
 27     }
 28     L.length = 0;
 29     L.listsize = LIST_INIT_SIZE;
 30 }
 31 
 32 //*********************输出线性表中的数据**************************
 33 void PrintList(SqList L)
 34 {
 35     int *p = L.elem; //顺序表的开始位置
 36     int *q = L.elem + L.length - 1;//顺序表的结束位置
 37     while(p<=q)
 38     {
 39         printf("%d ", *p++);
 40     }
 41 }
 42 
 43 //*************************线性表的插入****************************
 44 //*******参数i代表插入位置,在第i个之前插入*,故 1<=i<=n+1*********
 45 /**
 46 一般情况下,在第i(1<=i<=n)个元素之前插入,需要将第i至n(n-i+1)个元素向后移动一个位置,
 47 若i=n+1,则直接在插入在最后即可
 48 */
 49 void ListInsert(SqList &L,int i,int e)
 50 {
 51     //在顺序线性表L中的第i个位置之前插入新的元素e
 52     //i的合法值为1<=i<=ListLength(L)+1
 53     if (i<1||i>L.length+1)
 54     {
 55         printf("输入的插入位置不合法,请确定后重新输入!任意键退出\n");
 56         getchar();
 57         exit(1);
 58     }
 59     if (L.length >= L.listsize)
 60     {
 61         //当前存储空间已满,需要增加分配
 62         int * newbase = (int *)realloc(L.elem,(L.listsize + LISTINCREMENT)*sizeof(int));
 63         if (!newbase)
 64         {
 65             printf("存储分配失败,任意键退出!\n");
 66             getchar();
 67             exit(1);
 68         }
 69         L.elem = newbase;//新基址
 70         L.listsize += LISTINCREMENT;//增加存储容量
 71     }
 72     int * q = &(L.elem[i-1]);//q为插入位置
 73     for (int * p = &(L.elem[L.length-1]); p >= q; --p)
 74     {
 75         *(p+1) = *p;//插入位置及其之后的元素右移
 76     }
 77     *q = e;//插入e
 78     ++L.length;//表长加1
 79 }
 80 
 81 //***************************顺序线性表的删除******************************
 82 /**
 83 参数i代表删除位置,1<=i<=n,和插入时i的取值范围不同
 84 一般情况下,删除第i(1<=i<=n)个元素时需要将从第i+1至第n(n-i)个元素依次向前移动一个位置
 85 */
 86 void ListDelete(SqList &L,int i)
 87 {
 88     //删除顺序线性表中的第i个元素,i的合法值为1<=i<=ListLength(L)
 89     if (i<1 || i>L.length)
 90     {
 91         printf("输入的删除位置不合法,请确定后重新输入!任意键退出!\n");
 92         getchar();
 93         exit(1);
 94     }
 95     int * p = &(L.elem[i-1]);//p为删除位置
 96     int * q = L.elem + L.length - 1;//q为表尾位置
 97     for (++p ; p<=q; ++p)
 98     {
 99         *(p-1) = *p;//被删除元素之后的元素左移
100     }
101     --L.length;//表长减1
102 }
103 
104 //************数值定位函数,返回元素e在L中的位置,若没有,返回0***************
105 int LocateElem(SqList L,int e)
106 {
107     //在顺序线性表中查找第一个与元素e相同位序
108     //若找到,则返回其在L中的位序,否则返回0
109     int i = 1;//i的初始值为第一个元素的位序
110     int *p = L.elem ;//p的初始值为第一个元素的存储位置
111     while(i<=L.length && e != *p)
112     {
113         ++i;
114         ++p;
115     }
116     if (i<=L.length)
117         return i;
118     else
119         return 0;
120 }
121 
122 //**********************取出指定位序的线性表中的数据元素***********************
123 int GetElem(SqList L,int i)
124 {
125     //将线性表L中的第i个元素返回给e
126     if (i<1 || i>L.length)
127     {
128         printf("该数据元素不存在,请仔细确认!任意键退出\n");
129         getchar();
130         exit(1);
131     }
132     // int *q = &L.elem[i-1];
133     // int e = *q;
134     int e = L.elem[i-1];
135     //因为elem是一个数组指针,当只用elem时,代表首地址
136     //,若具体指定某一个数elem[i],则代表第i+1个元素,故下面和上面的注释方法都可行
137     // int *p = L.elem;
138     // int e = *(p+i-1);
139     return e;
140 
141 }
142 
143 //****************************线性顺序表的合并********************************
144 /**
145 该方法的线性复杂度为O(ListLength(LA) x ListLength(LB) )
146 该方法得到的线性表是无序的,数据直接插在一个线性表的最后
147 是将所有在线性表Lb中但不在La中的数据元素插入到La中,无重复项
148 */
149 void ListUnoin(SqList &La,SqList Lb)
150 {
151     //将所有在线性表Lb中但不在La中的数据元素插入到La中
152     int la_len = La.length;
153     int lb_len = Lb.length;
154     int e;
155     for (int i = 1; i <= lb_len; ++i)
156     {
157         e = GetElem(Lb,i);//取Lb中第i个元素赋值给e
158         //printf("%d\n",e);
159         if(!LocateElem(La,e))
160         {
161             ListInsert(La,++la_len,e);//将数据插在La的末尾
162         }
163     }
164 }
165 
166 //**************************有序线性顺序表的合并*******************************
167 /**
168 通过增加一个线性表,使得时间复杂度由O(ListLength(LA) x ListLength(LB))变成
169 了O(ListLength(LA) + ListLength(LB))
170 不过使用这种方法需要有个前提:La和Lb已经排序
171 得到的结果Lc也是排好序的线性表
172 */
173 void MergeList(SqList La,SqList Lb,SqList &Lc)
174 {
175     //本例中以非递减排序为例
176     int * pa = La.elem;
177     int * pb = Lb.elem;
178     Lc.length = La.length + Lb.length;
179     Lc.listsize = Lc.length;
180     Lc.elem = (int *)malloc(Lc.listsize * sizeof(int));
181     if (!Lc.elem)
182     {
183         printf("存储分配失败,任意键退出!\n");
184         getchar();
185         exit(1);
186     }
187     int *pc = Lc.elem;
188     int *pa_last = La.elem + La.length - 1;
189     int *pb_last = Lb.elem + Lb.length - 1;
190     while(pa<=pa_last && pb<=pb_last)//归并操作
191     {
192         if(*pa <= *pb)
193             *pc++ = *pa++;
194         else
195             *pc++ = *pb++;
196     }
197     while(pa <= pa_last)
198         *pc++ = *pa++;//插入La的剩余元素
199     while(pb <= pb_last)
200         *pc++ = *pb++;//插入Lb的剩余元素
201 }
202 
203 
204 int  main()
205 {
206     //首先输入10个数据,构造一个线性表,测试建表,输出,插入,删除功能是否正确
207     SqList La,Lb,Lc;
208     InitList(La);
209     InitList(Lb);
210     InitList(Lc);
211     int count,value,location;
212     printf("请输入建立顺序表La的元素个数:");
213     scanf("%d",&count);
214     printf("请依次输入%d个数据:",count);
215     for (int i = 0; i < count; ++i)
216     {
217         //将输入的数据插入到顺序表La中
218         scanf("%d",&value);
219         ListInsert(La,i+1,value);
220     }
221     //输出线性表的数据
222     printf("该顺序线性表的数据元素为:");
223     PrintList(La);
224 
225     //测试插入数据是否可行
226     printf("\n请输入插入位置和插入值:");
227     scanf("%d%d",&location,&value);
228     ListInsert(La,location,value);
229     printf("插入之后的数据元素为:");
230     PrintList(La);
231 
232     //测试删除数据情况
233     printf("\n请输入删除位置:");
234     scanf("%d",&location);
235     ListDelete(La,location);
236     printf("数据删除之后的元素为:" );
237     PrintList(La);
238 
239     //测试顺序表的合并,需要两个有序的顺序表
240     printf("\n请输入建立顺序表Lb的元素个数:");
241     scanf("%d",&count);
242     printf("请依次输入%d个数据:",count);
243     for (int i = 0; i < count; ++i)
244     {
245         //将输入的数据插入到顺序表La中
246         scanf("%d",&value);
247         ListInsert(Lb,i+1,value);
248     }
249     MergeList(La,Lb,Lc);
250     printf("将La和Lb合并之后的Lc数据元素为:");
251     PrintList(Lc);
252 
253     printf("\n采用时间复杂度更高的合并方式为:");
254     ListUnoin(La,Lb);
255     PrintList(La);
256 
257     return 0;
258 }

 

 

线性表的顺序存储

标签:

原文地址:http://www.cnblogs.com/wujiyang/p/4334357.html

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