[关闭]
@rg070836rg 2015-08-16T15:04:49.000000Z 字数 6085 阅读 1435

线性表的实现及其功能的拓展

data_structure

返回目录


本文目的在于,对线性表实现的描述,以及代码的简单实现

线性表概况描述

下面是函数的头文件部分

  1. template <class dataType, int MaxSize>class SeqList {
  2. dataType *data; //用于存放数据元素的数组
  3. int length; //顺序表中的元素个数
  4. public:
  5. SeqList(); //无参构造函数
  6. SeqList(dataType a[], int n); //有参构造函数
  7. ~SeqList();
  8. int ListLength(); //求线性表的长度
  9. void SetLength(int length);
  10. dataType Get(int pos); //按位查找,取顺序表的第pos个元素
  11. int Locate(dataType item); //按值查找,求顺序表中值为item的元素序号
  12. void PrintSeqList(); //遍历顺序表,按序号一次输出各元素
  13. void Insert(int i, dataType item); //在顺序表第i个位置插入值为item的元素
  14. dataType Delete(int i); //删除顺序表的第i个元素‘
  15. *****
  16. 扩展部分
  17. *****
  18. void quicksort(const int &first, const int &last );//快速排序
  19. void Merge(SeqList & LA, SeqList & LB); //合并有序表
  20. bool IsOrder(); //判断表是否有序
  21. dataType DeleteMinData(); //删除最小元素,空位后值填补
  22. void DeleteStoT(dataType S,dataType T); //删除S-T的元素
  23. void DeleteXitem(dataType X); //删除元素X
  24. void Deleterepeated(); //删除重复元素
  25. bool IsExited(dataType &x,dataType *record,int length);//查看元素是否已存在
  26. void DevidedBya_1(); //按照键值A1分开数组
  27. bool cmp(const dataType&, const dataType&); //用于比较
  28. };

一、基本功能

1.1无参构造函数

这个函数,适用于无参的构造函数,实现对空间的申请,以及长度置0;

  1. /**
  2. * 无参数构造函数
  3. * 仅设置长度为0
  4. * @param[in] 无
  5. */
  6. template<class dataType, int MaxSize>
  7. SeqList<dataType, MaxSize>::SeqList()
  8. {
  9. data=new dataType[MaxSize];
  10. length = 0;
  11. }

1.2有参构造函数

此函数用来,带有参数的赋值,做合法性检查,申请空间,置线性表长度。

  1. /**
  2. * 构造函数
  3. * 设置线性表的初始值,长度
  4. * @param[in] 数据源a,数量n
  5. */
  6. template<class dataType, int MaxSize>
  7. SeqList<dataType, MaxSize>::SeqList(dataType *a, int n)
  8. {
  9. data=new dataType[MaxSize];
  10. if (n > MaxSize) //数据合法性检查
  11. {
  12. cerr << "error";
  13. system("pause");
  14. exit(1);
  15. }
  16. for (int i=0; i <n; i++)
  17. {
  18. data[i] = a[i]; //需要重载运算符‘=’
  19. }
  20. length = n;
  21. cout << "\ncreate list success,length is " << length << endl;
  22. }

1.3析构函数

用于在程序结束后,对申请空间进行销毁,做后续处理。

  1. * 析构函数
  2. * @param[in]
  3. */
  4. template<class dataType, int MaxSize>
  5. SeqList<dataType, MaxSize>::~SeqList()
  6. {
  7. if(data) delete[]data;
  8. data=NULL;
  9. }

1.4求表长

  1. /**
  2. * 返回线性表返回当前元素个数
  3. * @param[out] 表长length
  4. */
  5. template<class dataType, int MaxSize>
  6. int SeqList<dataType, MaxSize>::ListLength()
  7. {
  8. return length;
  9. }

1.5其他基本功能

还有一些基本功能,不在此贴出,详细请见源程序

二、扩展功能

2.1快速排序

本函数采用快速排序的方法,对成员进行排序,目前采用的是运用cmp函数,以后可考虑用‘<’重载

  1. /**
  2. * 按照CMP的方式进行快速排序
  3. * @param[in] 起始位置first,终止位置last,比较函数cmp
  4. * 位置从0开始。
  5. */
  6. template<class dataType, int MaxSize>
  7. void SeqList<dataType, MaxSize>::quicksort(const int &first, const int &last)
  8. {
  9. int i = first, j = last;
  10. const dataType m = *(data + ((first + last) >> 1));
  11. dataType temp;
  12. do
  13. {
  14. while (cmp(data[i], m)) i++;
  15. while (cmp(m, data[j])) j--;
  16. if (i <= j)
  17. {
  18. temp = data[i];
  19. data[i] = data[j];
  20. data[j] = temp;
  21. i++; j--;
  22. }
  23. } while (i < j);
  24. if (i < last) quicksort( i, last);
  25. if (first < j) quicksort(first, j);
  26. }

2.2归并有序表

通过比较方法,取各数组较大值,最后把多余的附载在后面即可
其中,做了关于合法性的检测,还包含了先判断所给的数据是否有序的操作。

  1. /**
  2. * 合并两个有序表,并存在第一个中,
  3. * @param[in] 表1LA,表2LB, 比较方法,cmp
  4. * 位置从0开始。
  5. */
  6. template<class dataType, int MaxSize>
  7. void SeqList<dataType, MaxSize>::Merge(SeqList &LA,SeqList &LB)
  8. {
  9. int i = 0; int j = 0;int k = 0;
  10. SeqList C;
  11. if (LA.ListLength() + LB.ListLength() > MaxSize) {
  12. cerr << "溢出";
  13. system("pause");
  14. return;
  15. }
  16. C.length = LA.ListLength() + LB.ListLength();
  17. if(!LA.IsOrder(cmp)){LA.quicksort(0,LA.ListLength()-1,cmp);}//若A无序,先排序
  18. if(!LB.IsOrder(cmp)){LA.quicksort(0,LB.ListLength()-1,cmp);}
  19. while (i<LA.ListLength() && j<LB.ListLength()) {
  20. //循环,两两比较,小者存入结果表
  21. if (LA.data[i]<=LB.data[j])
  22. C.data[k++] = LA.data[i++];
  23. else
  24. C.data[k++] = LB.data[j++];
  25. }
  26. if(i==LA.ListLength()) {
  27. while (j< LB.ListLength()) {
  28. C.data[k++] = LB.data[j++];
  29. }
  30. }
  31. else{
  32. while (i<LA.ListLength()) {
  33. C.data[k++] = LA.data[i++];
  34. }
  35. }
  36. for (i=0;i<C.ListLength();i++)
  37. {
  38. LA.data[i]=C.data[i];
  39. }
  40. LA.SetLength(C.ListLength());
  41. }
  1. /*
  2. *检查元素是否有序
  3. */
  4. template<class dataType, int MaxSize>
  5. bool SeqList<dataType, MaxSize>::IsOrder()
  6. {
  7. for (int j = 0; j <ListLength() ; j++) {
  8. if (cmp(data[j], data[j + 1])) {
  9. return false;
  10. }
  11. }
  12. return true;
  13. }

2.3删除S-T之间元素

本函数比较复杂,目前版本没有实现完全功能,原因是没有重载运算符,对边界的处理不好。

  1. /**
  2. * 删除顺序表S-T之间元素,若S<T报错,
  3. * @param[in] S,T,
  4. * @param[out]
  5. * 位置从0开始。
  6. */
  7. template<class dataType, int MaxSize>
  8. void SeqList<dataType, MaxSize>::DeleteStoT(dataType S,dataType T)
  9. {
  10. if(!cmp(S,T))
  11. {
  12. cout<<"输入有误,删除失败。。"<<endl;
  13. return;
  14. }
  15. if (IsOrder()){
  16. quicksort(0,ListLength()-1);
  17. }
  18. for (int i=0;i<ListLength();i++){ //找到S所在的位置i
  19. bool flag = !cmp(data[i],S);
  20. if(flag){
  21. break;
  22. }
  23. }
  24. for (int j=0;j<ListLength();j++){ // 找到T所在的位置j
  25. bool flag = !cmp(data[j],T);
  26. if(flag){
  27. break;
  28. }
  29. }
  30. if(i>=0&&j<ListLength()){
  31. for(int k=j-1;k>=i;k--){
  32. Delete(k+1);
  33. }
  34. }
  35. }

2.3删除X元素

本函数用于删除顺序表中的X元素,未找到,提示消息。

  1. template<class dataType, int MaxSize>
  2. void SeqList<dataType, MaxSize>::DeleteXitem(dataType X){
  3. int k=0;
  4. for (int i=0;i<ListLength();i++)
  5. {
  6. if (X==data[i])
  7. {
  8. Delete(i+1);
  9. i=i-1;
  10. k++;
  11. }
  12. }
  13. if (k==0)cout<<"Not Found!"<<endl;
  14. }

2.4删除重复元素

本函数用于删除重复元素,编写时遍历表,找到第一次出现的元素,放在record数组中,后接受record的值

  1. /**
  2. * 删除重复元素
  3. * @param[in]
  4. * @param[out]
  5. * 位置从0开始。
  6. */
  7. template<class dataType, int MaxSize>
  8. void SeqList<dataType, MaxSize>::Deleterepeated(){
  9. dataType *record=new int[MaxSize];
  10. int k=0;
  11. for (int i=0;i<ListLength();i++)
  12. {
  13. if (!IsExited(data[i],record,k))
  14. {
  15. record[k++]=data[i];
  16. }
  17. }
  18. delete []data;
  19. data=record;
  20. SetLength(k);
  21. }

其中用了一个辅助函数,判定是否第一次出现。

  1. /**
  2. * 判定元素是否出现过,辅助函数
  3. * @param[in] 元素X,数组record,长度length
  4. * @param[out] bool flag
  5. * 位置从0开始。
  6. */
  7. template<class dataType, int MaxSize>
  8. bool SeqList<dataType, MaxSize>::IsExited(dataType &x,dataType *record,int length){
  9. for (int i=0;i<length;i++)
  10. {
  11. if(x==record[i]) return true;
  12. }
  13. return false;
  14. }

2.5 划分元素

按照A[0]值,划分数组,要求复杂度为O(n)
思路如下:先遍历一遍,找到小于键值的,放到前面(交换),从这个位置继续开始继续遍历,找到等于的元素放到中间即可。

  1. /**
  2. * 按照a0的值划分,要求时间复杂度为O(N)
  3. * @param[in]
  4. * @param[out]
  5. * 位置从1开始。
  6. */
  7. template<class dataType, int MaxSize>
  8. void SeqList<dataType, MaxSize>::DevidedBya_1(){
  9. dataType v=data[0];//键值V
  10. int k=0;//递进下标
  11. for (int i=0;i<ListLength();i++) //小于v的值归于左侧
  12. {
  13. if (data[i]<v)
  14. {
  15. int tmp=data[i];
  16. data[i]=data[k];
  17. data[k]=tmp;
  18. k++;
  19. }
  20. }
  21. for (i=k;i<ListLength();i++) //等于v的值继续归于中间,剩下的自然是大于v的值
  22. {
  23. if (data[i]==v)
  24. {
  25. int tmp=data[i];
  26. data[i]=data[k];
  27. data[k]=tmp;
  28. k++;
  29. }
  30. }
  31. }

三、测试(test.cpp)

下面是完整代码

  1. #include<iostream>
  2. #include<stdlib.h>
  3. #include"SeqList.h"
  4. #include"SeqList.cpp"
  5. using namespace std;
  6. int main() {
  7. int MaxSize=100;
  8. int number;
  9. cout << "请输入数据个数\n";
  10. cin >> number;
  11. int *a = new int[number];
  12. for (int i = 0; i < number; i++)
  13. {
  14. cin>>a[i];
  15. }
  16. SeqList<int, 100> lista(a, number);
  17. cout <<"当前元素个数是:"<< lista.ListLength()<< endl;
  18. lista.quicksort(0,lista.ListLength() - 1);
  19. cout << "排序后遍历打印:"<<endl;
  20. lista.PrintSeqList();
  21. system("pause");
  22. lista.DeleteStoT(70,90);
  23. cout << "删除S-T后遍历打印:"<<endl;
  24. lista.PrintSeqList();
  25. lista.Insert(1,3);
  26. cout << "插入后遍历打印:"<<endl;
  27. lista.PrintSeqList();
  28. lista.DeleteXitem(100);
  29. cout<<endl << "删除元素X后遍历打印:"<<endl;
  30. lista.PrintSeqList();
  31. system("pause");
  32. cout <<endl<< "按照a0划分遍历打印:"<<endl;
  33. lista.DevidedBya_1();
  34. lista.PrintSeqList();
  35. system("pause");
  36. cout <<endl<< "删除重复元素后遍历打印:"<<endl;
  37. lista.Deleterepeated();
  38. lista.PrintSeqList();
  39. system("pause");
  40. if (a) delete []a;//扫尾
  41. return 0;
  42. }

3.1测试结果

alt text

4、总结

这次编程,还算顺利,但是对于引用对象还是不是很清楚,感谢老师刚刚发的文件,会去仔细看看的。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注