数据结构--线性表

来源:互联网 发布:死亡宣告知乎 编辑:程序博客网 时间:2024/06/08 12:52

逻辑结构

集合结构、线性结构、树形结构、图形结构;

物理结构

顺序存储结构、链式存储结构;

算法的特性

输入:算法具有0个或多个输入,对绝大多数算法而言输入参数都是必要的;

输出:算法至少有1个或多个输出,算法一定有输出;

有穷性:算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成;

确定性:算法的每一个步骤都有明确的含义,不会出现二义性;算法在一定条件下,只有一条执行路径,相同的输入只能有唯一的输出结果;

可行性:算法的每一步都能够通过执行有限的次数完成;

算法设计的要求

正确性、可读性、健壮性、时间效率高和存储量低;

时间复杂度和空间复杂度

算法效率的度量方法:

事后统计方法、事前分析估算方法;

结论:判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高项)的阶数;


常数阶O(1)、线性阶O(n)、平方阶O(n^2)、对数阶O(logn)【2^x=n  》 x=log(2)n】

函数调用的时间复杂度分析:

O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n);

最坏情况和平均情况;

算法的空间复杂度:


线性表(List)

定义:由0个或多个数据元素组成的有限序列。


数据类型:是指一组性质相同的值的集合及定义在此集合上的一些操作的总称。

——原子类型:不可再分解的基本类型,例如整型、浮点型、字符型;

——结构类型:由若干个类型组合而成,是可以在分解的,例如整型数组是由若干整型数据组成的;

抽象数据类型(Abstract Data Type,ADT)是指一个数学模型及定义在该模型上的一组操作。抽象数据类型的定义仅取决于它的一组逻辑特性,而与其在计算机内部如何表示和实现无关。


ADT List

Data 

{a1,a2,...,an}

Operation


//La表示A集合,Lb表示B集合。void unionL(List *La,List Lb){int La_len,Lb_len,i;ElemType e;La_len = ListLength(*La)Lb_len = ListLength(Lb)for(i=1;i<=Lb_len;i++){GetElem(Lb,i,&e);if(!LocateElem(*La,e)){ListInsert(La,++La_len,e);}}}
线性表的顺序存储结构和链式存储结构

#define MAXSIZE 20typedef int ELemType;typedef struct{ElemType data[MAXSIZE]int length;//线性表当前长度}SqList;

对数组进行封装,增加了当前长度的变量。

——存储空间的起始位置,数组data,它的存储位置就是线性表存储空间的存储位置;

——线性表的最大存储容量:数组的长度MaxSize;

——线性表的当前长度:length。

地址计算方法:LOC(ai)=LOC(a1)+(i-1)*c

//getElem.c#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0typedef int Status;//Status是函数的类型,其值是函数结果状态代码,如OK等;//初识条件:顺序线性表L已存在,1<=i<=ListLength(L)//操作结果:是用e返回L中第i个数据元素的值Status GetElem(SqList L,int i,ElemType *e){if(L.length==0||i<1||i>L.length){return ERROR;}*e=L.data[i-1];return OK;}

/*初始条件:顺序线性表L已存在,1<=i<=Listlength(L)*//*操作结果:在L中第i个位置之前插入新的数据元素e,L的长度+1*/Status ListInsert(SqList *L,int i,ElemType e){int k;if(L->length==MAXSIZE)//顺序线性表已经满了{return ERROR;}if(i<1||i>L->length+1)//当i不在范围内时{return ERROR;}if(i<=L->length)//若插入数据位置不在表尾{/*将要插入位置后数据元素向后移动一位*/for(k=L->length-1;k>=i-1;k--){L->data[k+1]=L->data[k];}}L->data[i-1]=e;//将新元素插入L->length++;return OK;}

/*初始条件:顺序线性表L已存在,1<=i<=Listlength(L)*//*操作结果:删除L的第i个元素,并用e返回其值,L的长度-1*/Status ListDelete(SqList *L,int i,ElemType e){int k;if(L->length==0)//顺序线性表为空{return ERROR;}if(i<1||i>L->length)//当i不在范围内时{return ERROR;}*e = L->data[i-1];if(i < L->length)//若删除数据位置不在表尾{/*将要删除位置后数据元素向前移动一位*/for(k=i;k<L->length;;k++){L->data[k-1]=L->data[k];}}L->length--;return OK;}

时间复杂度:

最好情况O(1)

最坏情况O(n)

平均情况[O(1)+O(n)]/2


头指针与头结点的异同




结构指针描述单链表

typedef struct Node{ElemType data;   //数据域struct Node* Next;  //指针域} Node;typedef struct Node* LinkList;
/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)*//*操作结果:用e返回L中第i个数据元素的值*/Status GetElem(LinkList L,int i,ElemType *e){int j;LinkList P;P = L->next;j = 1;while(P && j<i){P = P->next;++j;}if(!P || j>i){return ERROR;}*e = P->data;return OK;}
单链表的插入

/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)*//*操作结果:在L中的第i个位置之前插入新的数据元素e,L的长度加1*/Status ListInsert(LinkList *L,int i,ElemType e){int j;LinkList p,s;p=*L;j=1;while(p&&j<i)//用于寻找第i个结点{p=p->next;j++;}if(!p || j>i){return ERROR;}s=(LinkList)malloc(sizeof(Node));s->data=e;s->next=p->next;p->next=s;return OK;}

/*初始条件:顺序线性表L已存在,1<=i<=ListLength(L)*//*操作结果:删除L中的第i个数据元素,并用e返回其值,L的长度-1*/Status ListInsert(LinkList *L,int i,ElemType e){int j;LinkList p,q;p=*L;j=1;while(p->next && j<i)//用于寻找第i个结点{p=p->next;j++;}if(!(p->next) || j>i){return ERROR;}q=p->next;p->next=q->next;*e=q->data;free(q);return OK;}
头插法建立单链表

/*头插法建立单链表示例*/void CreateListHead(LinkList *L,int n){LinkList p;int i;srand(time(0));//初始化随机数种子(*L)->next=NULL;for(i=0;i<n;i++){p=(LinkList)malloc(sizeof(Node));//生成新结点p->data=rand()%100+1;p->next=(*L)->next;(*L)->next=p;}}
尾插法建立单链表

/*尾插法建立单链表示例*/void CreateListTail(LinkList *L,int n){LinkList p,r;int i;srand(time(0));//初始化随机数种子*L = (LinkList)malloc(sizeof(Node));r=*L;for(i=0;i<n;i++){p=(Node *)malloc(sizeof(Node));//生成新结点p->data=rand()%100+1;r->next=p;r=p;}r->next=NULL;}















































0 0
原创粉丝点击