首先先说下什么是线性表。线性表是最简单的一种数据结构。通俗的来讲,一个线性表就是以n个数据元素的有限序列(相当于数学中的“有限个元素的数列”)。当n=0时,线性表是空表。 线性结构的特点: <1>:除第一个数据元素以外,每个数据元素都有前驱。 <2>:除最后一个数据元素以外,每个数据元素都有后继。 <3>:除以上两点外,每个数据元素都只有一个前驱和后继。 其次线性表的优缺点; 优点:访问某个位置的数据元素比较方便。 缺点:数据元素的插入和删除比较麻烦。时间复杂度也比较高。 现在来看一下怎么实现的。 先了解下其中的宏定义,以后的数据结构中也会用到同样的名称。
#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status;好了,现在才刚刚开始。 以下代码都是用C语言实现的。 首先是—–线性表的动态分配顺序存储结构——-
#define LIST_INIT_SIZE 100 //线性表初始空间分配量 #define LISTINCREMENT 10 //线性表空间分配的增量 typedef int ElemType; //这里用整型数据类型代替其他数据类型 typedef struct LNode { ElemType *elem; //存储空间的基地址 int lenght; //当前的长度 int listsize; //当前分配的存储容量 }SqList;接下来是创建一个空的线性表:
Status Listinit(SqList &L) { L.elem = (ElemType *)malloc( LIST_INIT_SIZE * sizeof(ElemType)); if(!L.elem) exit(OVERFLOW); //分配存储空间失败 L.lenght = 0; //初始空表长度为0 L.listsize = lenght ;//初始存储容量为100 return OK; }然后是对顺序线性表的插入进行的操作:
Status ListInsert(SqList &L, ElemType e, int i) { ElemType *p, *q; if(i<=0 ||i > L.lenght+1) return ERROR; //i值不合法 if (L.lenght >= L.listsize) { ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize +LISTINCREMENT)*sizeof(ElemType)); if(!newbase) return OVERFLOW; //存储分配失败 L.elem = newbase; //新基值 L.listsize += LISTINCREMENT; //增加存储容量 } q = &L.elem[i-1]; //q为插入的位置 for (p = &L.elem[L.lenght]; p>=q; --p) { *p = *(p-1); //i元素之后的元素往后移动 } *q = e; //插入e L.lenght +=1; return OK; }嗯,看的可能有点不耐烦了,什么乱七八糟的变量名,其实我也不适应。然而需要学习这么课程所以还是耐心点看下去把。 删除操作也很简单直接上代码把:
Status ListDelete(SqList &L, int i, ElemType &e) { int *p, *q; //Status相当于int还是不太习惯写。 if(i<1 ||i > L.lenght) return ERROR; //i值不合法 ,超过了线性表的长度或者在第一个元素前面当然就是不合法了。 q = &L.elem[i-1]; //被删除元素的位置为i,i从0开始的所以是i-1; e = *q; //被删除元素的值赋值给e for (p = q; p< (L.elem + L.lenght-1);p++) { //元素左移 *(p)=*(p+1); } L.lenght--; return OK; }接着看下对线性表中某个元素的查找
int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))//这里是一个指针函数,传参数时只需要穿函数名就行 { int i=0; ElemType *p=L.elem; while(i<L.lenght&&!(*compare)(*p++,e))++i; if(i<L.lenght)return i+1;//因为从0开始的所以是i+1; else return 0; } int compare(ElemType x,ElemType y)//两个数相等的函数 { return x==y; }最后一个合并两个线性表开不开心,终于要结束了。
void mergeList(SqList La, SqList Lb, SqList &Lc) { int *pa, *pb, *pc; //ElemType一样的。 Lc.listsize = La.lenght + Lb.lenght; initList(Lc, Lc.listsize); //初始化LC\pc = Lc.elem; Lc.lenght = Lc.listsize; pc = Lc.elem; pa = La.elem; pb = Lb.elem; while (pa <= &La.elem[La.lenght -1] && pb <= &Lb.elem[Lb.lenght -1]) { if (*pa <= *pb) *pc++ = *pa++; else *pc++ = *pb++; } while(pa <= &La.elem[La.lenght -1]) *pc++ = *pa++; //插入La的剩余元素 while(pb <= &Lb.elem[Lb.lenght -1]) *pc++ = *pb++; //插入Lb的剩余元素 }基本操作就基本结束了。接下来放一份完整的代码,仅供参考:
#include <stdio.h> #include<stdlib.h> #include<iostream> using namespace std; //宏定义 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define LT(a,b) ((a)<(b)) #define N = 100 #define LIST_INIT_SIZE 100 //线性表初始空间分配量 #define LISTINCREMENT 10 //线性表空间分配的增量 typedef int Status; typedef int ElemType; typedef struct LNode { ElemType *elem; //存储空间的基地址 int lenght; //当前的长度 int listsize; //当前分配的存储容量 }SqList; //构造空的线性表 Status Listinit(SqList &L) { L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType)); if(!L.elem) exit(OVERFLOW); //分配存储空间失败 L.lenght = 0; //初始空表长度为0 L.listsize = LIST_INIT_SIZE ;//初始存储容量为100 return OK; } //对顺序线性表的插入进行的操作: Status ListInsert(SqList &L, ElemType e, int i) { ElemType *p, *q; if(i<=0 ||i > L.lenght+1) return ERROR; //i值不合法 if (L.lenght >= L.listsize) { ElemType *newbase = (ElemType *)realloc(L.elem ,(L.listsize +LISTINCREMENT)*sizeof(ElemType)); if(!newbase) return OVERFLOW; //存储分配失败 L.elem = newbase; //新基值 L.listsize += LISTINCREMENT; //增加存储容量 } q = &L.elem[i]; //q为插入的位置 for (p = &L.elem[L.lenght-1]; p>=q; --p) { *p = *(p-1); //i元素之后的元素往后移动 } *q = e; //插入e L.lenght +=1; return OK; } //线性表的删除操作: Status ListDelete(SqList &L, int i, ElemType &e) { int *p, *q; //Status相当于int还是不太习惯写。 if(i<1 ||i > L.lenght) return ERROR; //i值不合法 ,超过了线性表的长度或者在第一个元素前面当然就是不合法了。 q = &L.elem[i-1]; //被删除元素的位置为i,i从0开始的所以是i-1; e = *q; //被删除元素的值赋值给e for (p = q; p< (L.elem + L.lenght-1);p++) { //元素左移 *(p)=*(p+1); } L.lenght--; return OK; } //在线性表中查找某个元素 int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))//这里是一个指针函数,传参数时只需要穿函数名就行 { int i=0; ElemType *p=L.elem; while(i<L.lenght&&!(*compare)(*p++,e))++i; if(i<L.lenght)return i+1;//因为从0开始的所以是i+1; else return 0; } int compare(ElemType x,ElemType y)//两个数相等的函数 { return x==y; } //合并两个线性表 void mergeList(SqList La, SqList Lb, SqList &Lc) { int *pa, *pb, *pc; //ElemType一样的。 Listinit(Lc); //初始化LC\pc = Lc.elem; // Lc.lenght = Lc.listsize; Lc.lenght=La.lenght + Lb.lenght; pc = Lc.elem; pa = La.elem; pb = Lb.elem; while (pa <= &La.elem[La.lenght -1] && pb <= &Lb.elem[Lb.lenght -1]) { if (*pa <= *pb) *pc++ = *pa++; else *pc++ = *pb++; } while(pa <= &La.elem[La.lenght -1]) *pc++ = *pa++; //插入La的剩余元素 while(pb <= &Lb.elem[Lb.lenght -1]) *pc++ = *pb++; //插入Lb的剩余元素 } int main() { SqList La,Lb,Lc; ElemType e; int init,i; Listinit(La); printf("请输入要输入的元素个数:\n"); scanf("%d",&La.lenght); for(int i=0;i<La.lenght;i++)//事例先输入10个数,大小可以自己更改 { scanf("%d",&La.elem[i]); } for(int i=0;i<La.lenght;i++) { printf("%d ",La.elem[i]);//输出顺序线性表 } cout<<endl; printf("请输入要查找的元素\n"); int u; scanf("%d",&u); int z=LocateElem(La,u,compare);//查找元素2是否在该线性表中 if(z) printf("查找的元素在第%d个位置上\n",z); else printf("该线性表中不存在该元素\n"); int mi,w; printf("请输入要插入的元素和位置\n"); scanf("%d%d",&mi,&w); int flag=ListInsert(La,mi,w);//在第w个位置插入一个数据元素 mi if(flag) printf("插入成功\n"); else printf("插入失败\n"); for(int i=0;i<La.lenght;i++) { printf("%d ",La.elem[i]);//输出插入后的顺序线性表 } printf("\n"); int m,k;//被删除的元素赋给m printf("请输入要删除的元素\n"); scanf("%d",&k); ListDelete(La,k,m); for(int i=0;i<La.lenght;i++) { printf("%d ",La.elem[i]); } printf("\n%d元素已经被删除\n",m); Listinit(Lb); printf("请输入另一个线性表的元素个数\n"); scanf("%d",&Lb.lenght); for(int i=0;i<Lb.lenght;i++)//输入另一个顺序线性表 { scanf("%d",&Lb.elem[i]); } for(int i=0;i<Lb.lenght;i++) { printf("%d ",Lb.elem[i]);//输出另一个顺序线性表 } printf("\n"); mergeList(La,Lb,Lc);//合并两个线性表 printf("输出合并后的线性表的长度\n"); for(int i=0;i<Lc.lenght;i++)//输出两个线性表 { printf("%d ",Lc.elem[i]); } return 0; }