数据结构-----线性表的顺序表示与实现
废话不多说,直接粘代码,一切尽在代码中。
LIST.h当中代码:
/* * Copyright (c) 2014,个人所有 * All rights reserved. * * 文件名称:LIST.h * 文件标识:见配置管理计划书 * 摘 要:线性表的顺序存储 * * 当前版本:1.1 * 作 者:zhuxuekui3 * 完成日期:2014年5月4日 * * 取代版本:1.0 * 原作者 :zhuxuekui3 * 完成日期:2014年5月3日 */ #ifndef LIST_H #define LIST_H #include <iostream> using namespace std; //定义函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -1 #define UNDERFLOW -2 /********线性表的动态分配顺序存储结构******/ const int LIST_INIT_SIZE = 100; const int LISTINCREMENT = 10; typedef int ElemType; typedef int Status; typedef bool (* comparePtr)(ElemType,ElemType); //comparePtr compare; //用comparePtr来申明全局compare变量 typedef struct SqList { ElemType *elem; //存储空间基址 , 数组指针elem指示线性表的基地址。数组首地址 int length; //当前长度,记录数组的长度 int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位) } SqList; //初始化顺序表 Status InitList_Sq(SqList &L); //在顺序表L中第i个位置之前插入新的元素e Status ListInsert_Sq(SqList &L,int i,ElemType e); //在顺序表L中第i个位置删除元素e,并用e返回其值 Status ListDelete_Sq(SqList &L,int i,ElemType &e); //改.C文件的同时必须改声明 //将顺序表中的元素输出 Status ListPrint_Sq(SqList &L); //对无序的两个顺序表求并集 void union1(SqList &La, SqList &Lb); void union2(SqList &La, SqList &Lb); bool equal(ElemType a, ElemType b); //在顺序表中查找与e相同的元素,并返回e所在的位置 //int LocateElem_Sq(SqList &L,ElemType e,bool (* compare)(ElemType,ElemType)); int LocateElem_Sq(SqList &L,ElemType e,comparePtr compare); //取顺序表中第i个元素赋给e Status GetElem(SqList &L,int i,ElemType &e); //好像对不需要传回来的数据,并不需要用引用,用形参就可以了 void MergeList_Sq(SqList La,SqList Lb,SqList &Lc); #endif
LIST.cpp代码:
/* * Copyright (c) 2014,个人所有 * All rights reserved. * * 文件名称:LIST.cpp * 文件标识:见配置管理计划书 * 摘 要:线性表的顺序存储 * * 当前版本:1.1 * 作 者:zhuxuekui3 * 完成日期:2014年5月4日 * * 取代版本:1.0 * 原作者 :zhuxuekui3 * 完成日期:2014年5月3日 */ #include "stdafx.h" #include "LIST.h" int main() { ElemType e; SqList L; SqList L1; SqList L2;//无需要初始化,会在函数当中初始化 InitList_Sq(L); InitList_Sq(L1); //InitList_Sq(L2); ListInsert_Sq(L,1,9); ListInsert_Sq(L,2,7); ListInsert_Sq(L,3,4); ListInsert_Sq(L,4,2); ListPrint_Sq(L); ListInsert_Sq(L1,1,8); ListInsert_Sq(L1,2,6); ListInsert_Sq(L1,3,5); ListInsert_Sq(L1,4,3); ListPrint_Sq(L1); MergeList_Sq(L,L1,L2); //union2(L,L1); //ListDelete_Sq(L,1,e); //cout << e << endl; ListPrint_Sq(L2); return 0; } //初始化线性表 Status InitList_Sq(SqList &L) { L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType)); if (!L.elem) { exit(OVERFLOW); } L.length = 0; //空表的长度为0 L.listsize = LIST_INIT_SIZE; //初始存储容量 return OK; } //在顺序表L中第i个位置之前插入新的元素e Status ListInsert_Sq(SqList &L,int i,ElemType e) { // 1<=i<=L.length + 1; 有效范围 if(i<1 || i>L.length + 1) return ERROR; if (L.length > L.listsize)//当前分配的内存已满,已int为一个单位,需要重新开辟内存空间 { ElemType* newbase = (ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType)); if (!newbase)//分配未成功 { exit(OVERFLOW); } L.elem = newbase;//new address L.listsize += LISTINCREMENT;// add store memery } ElemType * q = &(L.elem[i-1]); ElemType * p = &(L.elem[L.length - 1]); //这里可以改为 = L.elem + L.length - 1; for (p; p >= q; --p) //一直循环到p = q为止 { *(p+1) = *p; //小下标的数,返回给大下标的数 } *q = e; //插入e; ++L.length; //表长加1; return OK; } Status ListDelete_Sq(SqList &L,int i,ElemType &e) { if(i<1 || i>L.length + 1) return ERROR; ElemType *q = &(L.elem[i-1]); ElemType *p = &(L.elem[L.length-1]); e = *q; for (q;q<=p;++q) //将下标大的数赋值给下标小的数 { *q = *(q+1); } --L.length; return OK; } Status ListPrint_Sq(SqList &L) { ElemType *p = &(L.elem[0]); ElemType *q = &(L.elem[L.length-1]); for (p;p<=q;++p) { cout << *p << " "; } cout << endl; return OK; } //对无序的两个顺序表求并集 /* 有两种思路,要么重新开辟一个Lc,然后将两者插入进去,不允许重复。但操作这种方法时候, 要求我们先排序。这样操作才方便些。时间复杂度Length(La)+Length(Lb). 或者,我们用控制变量法,这种方法时间复杂度Length(La)*Length(Lb). 说白了,就是以空间换时间,或者以时间换空间,别无其他。 */ //时间复杂度Length(La)*Length(Lb),节省了空间。 //下面语句是提取相同的元素到La中去,不是求并集,切记。 void union1(SqList &La, SqList &Lb) { ElemType *q1 = &(La.elem[0]); ElemType *p1 = &(La.elem[La.length-1]); ElemType *q2 = &(Lb.elem[0]); ElemType *p2 = &(Lb.elem[Lb.length-1]); ElemType *temp = q2; //这里面是用的常量在初始化,并不是用变量在初始化指针。 int count = 1; /*下面的语句,用&(La.elem[La.length-1]),不可用p1,p1是不变的,而我们插入的话 La是在变动的,所以不可以用一个不变的东西去代替。但p2是不变的,无所谓。 */ for(q1; q1<= &(La.elem[La.length-1]); ++q1) { for (q2;q2<=p2;++q2) { if (*q1==*q2) { ListInsert_Sq(La,count,*q1); ++q1; //注意:La是在变动的。 ++count; //严格控制插入的位置,La在变,指针位置相对的移动一个位置,所以 //与La相关的count也是需要变动的。 } } q2 = temp; ++count; } } //将所有在Lb中但不在La中的数据元素插入到La中去 void union2(SqList &La, SqList &Lb) { int La_Len = La.length; int Lb_Len = Lb.length; ElemType e = 0; for (int i = 1; i <= Lb_Len; ++i) { GetElem(Lb,i,e);//取Lb中的第i个数据元素赋给e if (!LocateElem_Sq(La,e,equal))//La中不存在和e相同的元素,则插入 { ListInsert_Sq(La,++La_Len,e); } } } //在顺序表中查找与e相同的元素,并返回e所在的位置 comparePtr compare //int LocateElem_Sq(SqList &L,ElemType e,bool (* compare)(ElemType,ElemType)) int LocateElem_Sq(SqList &L,ElemType e,comparePtr compare) { //若找到,则返回其在L中的位置,否则返回0; int i = 1; ElemType *p = L.elem;//第一个元素的位置 while(i <= L.length && !(compare(*p++,e))) ++i; //这里通过compare指针来执行传递过来的函数 if (i <= L.length) //注意:compare所指的函数是有一个参数的。 { return i; } else { return 0; } } Status GetElem(SqList &L,int i,ElemType &e) { if(i<1 || i>L.length + 1) return ERROR; e = L.elem[i-1]; return OK; } bool equal(ElemType a, ElemType b) { if (a == b) { return true; } else { return false; } } //已知顺序表中La与Lb有序,归并 void MergeList_Sq(SqList La,SqList Lb,SqList &Lc) { ElemType *pa = La.elem; ElemType *pa_last = La.elem + La.length - 1; ElemType *pb = Lb.elem; ElemType *pb_last = Lb.elem + Lb.length - 1; Lc.length = La.length + Lb.length; Lc.listsize = Lc.length;//数组的长度 Lc.elem = (ElemType *)malloc(Lc.listsize*sizeof(ElemType));//数组的容量 if (!Lc.elem) //内存分配失败 ,即返回0,!之后就变成真了。 { exit(OVERFLOW); } ElemType *pc = Lc.elem; while(pa <= pa_last && pb <= pb_last) //降序排列 { if (*pa < *pb) { *pc++ = *pb++; //pc是需要移动的 } else if (*pa == *pb) { *pc++ = *pa++; pb++; } else { *pc++ = *pa++; } } while(pa <= pa_last) *pc++ = *pa++; while(pb <= pb_last) *pc++ = *pa++; }