目录
数据逻辑结构
1.集合结构
2.线性结构
3.树形结构
4.图形结构
数据的物理结构
1.顺序结构
2.链式结构
3.索引结构
4.散列结构
算法的五个特征
1.有穷性
2.确定性
3.有效性
4.有0个或多个输入
5.有1个或多个输出
时间复杂度
算法中执行次数最多的那条语句的执行次数,通常是最内层循环的循环体。
空间复杂度
执行算法所需要的存储空间
线性表
顺序存储的线性表
顺序表结构
#define INIT_SIZE 100 //线性表存储空间的 初始分配量
#define INCREMENT 10 // 线性表存储空间的 分配增量
typedef int ElemType; // 定义元素类型为int
typedef struct
{
ElemType *elem; // 存储空间的基地址
int length; // 当前长度
int listsize; //当前分配的存储容量(以 sizeof(ElemType)为单位)
}SqList;
初始化表
int InitList_Sq(SqList *L)//初始化顺序表,成功返回1,失败返回0
{
L->elem=(ElemType *)malloc(INIT_SIZE*sizeof(ElemType));
if(!L->elem) return 0; //初始化失败
L->length=0;
L->listsize=INIT_SIZE;
return 1; //初始化成功
}
插入操作
//在顺序表L的第i个位置之前插入新的元素e,若插入成功则返回1,否则返回0
int ListInsert_Sq(SqList *L,int i,ElemType e)
{
int j;
ElemType *newbase;
if(i<0 || i>L->length)
return 0; //插入位置不合法,插入失败
if(L->length>=L->listsize) //当前存储空间已满,增加分配空间
{
newbase=(ElemType *)realloc(L->elem,(L->listsize+INCREMENT)*sizeof(ElemType));
if(!newbase) return 0; //存储分配失败,插入失败
L->elem = newbase;
L->listsize += INCREMENT;
}
for(j=L->length-1;j>=i;j--)
{
L->elem[j+1] = L->elem[j]; //插入位置及之后的元素从后开始向后移动
}
L->elem[i]=e; //插入e
++L->length; //表长增1
return 1; //插入成功
}
删除操作
int ListDelete_Sq(SqList *L,int i,ElemType *e)
{
int j;
if(i<0 || i>L->length-1) return 0
*e=L->elem[i]; //将被删除元素的值赋给e
for(j=i+1; j<=L->length-1; j++)
{
L->elem[j-1]=L->elem[j]; --L->length;
}
return 1; //删除成功
}
按值查找位置
//在顺序线性表L中查找第1个值与e相等的元素的位序,若找到,则返回其在L中的位序,否则返回-1
int LocateElem_Sq(SqList L, ElemType e)
{
int i=0; //i的初值为最前面一个元素的位序
while(i<L.length&&L.elem[i]!=e) //从前向后逐一比较
i++;
if(L.elem[i]==e) //查找成功,i为与e相等的第一个元素的位序
return i;
else
return -1; //查找失败
}
按位置取值
//在顺序线性表L中取第i个元素存入e中,若成功,则返回1,否则返回0
int Get_SqList(SqList L,int i,ElemType *e)
{
if(i<0||i>L.length-1)
return 0;//没有第i个元素,读取失败
*e=L.elem[i];
return 1; //读取成功
}
将两个从小到大排序的顺序表,归并成一个
//已知顺序线性表LA和LB的元素按值非递减排列,归并LA和LB得到新的顺序线性表LC,LC的元素也按值非递减排列,成功返回1,失败返回0
int MergeList_Sq(SqList LA, SqList LB, SqList* LC)
{
int i=0,j=0,k=0;
LC->listsize = LA.length + LB.length;//拿到LC的长度
LC->elem=(ElemType*)malloc(LC->listsize*sizeof(ElemType));//给LC分配空间
if(!LC->elem) return 0;
while(i<LA.length&&j<LB.length)
{
if(LA.elem[i]<=LB.elem[j])
LC->elem[k++] =LA.elem[i++];
else
LC->elem[k++]=LB.elem[j++];
}
while(i<LA.length) LC->elem[k++]=LA.elem[i++];
while(j<LB.length) LC->elem[k++]=LB.elem[j++];
LC->length=k;
return 1;
}
链式存储的线性表(不带头节点)
链表结构
//建立链表结点
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
头插入法建立单链表
//建立一个单链表L,输入n个元素的值
LinkList CreatHead_LinkList(int n)
{
LinkList L=NULL;//建立空链表L
LNode *s;
int i;
for(i=0; i<=n-1; i++)
{
s=(LNode *)malloc(sizeof(LNode));//生成新节点
printf("请输入第%d个元素的值:",i);
scanf("%d",&s->data);//输入元素值
s->next=L;
L=s;
}
return L;
}
尾插入法建立单链表
//建立一个单链表L,输入n个元素的值
LinkList CreatRear_LinkList(int n)
{
LinkList L=NULL;//定义一个空表
LNode *s,*r=NULL;//定义新节点指针和尾指针
int i;
for(i=0; i<=n-1; i++)
{
s=(LNode *)malloc(sizeof(LNode));//生成新节点
printf("请输入第%d个元素的值:",i);
scanf("%d",&s>data); //输入元素值
if(L==NULL) //插入的节点是最前面的节点
L=s;
else //插入的节点是第一个以外的节点
r->next=s;
r=s; //r恒指向插入后的链表尾节点
}
if(r!=NULL)//如果链表非空,则尾节点的指针域置为空
r->next=NULL
return L;
}
求单链表的表长(长度不是从0开始算)
//当链表不带头节点时
int Length_LinkList2(LinkList L)
{
LNode *p=L;
int i; //设计数器变量i
if(p==NULL) return 0; //为空表返回0
i=1; //为非空表,p指向最前面的节点
while(p->next)
{ p=p->next;i++; }
return i;
}
链式存储的线性表(带头节点)
初始化
//构建一个带头节点的空链表,用L返回其头指针,若失败则返回0
LinkList Init_LinkList(LinkList L)
{
L=(LNode *)malloc(sizeof(LNode));//分配一个头节点
if(!L) return 0; //分配失败
L->next = NULL; //头节点的指针域为空
return L;
}
尾插入法建立单链表
//建立带头节点的单链表L,输入n个元素的值
LinkList Create_LinkList (int n)
{
LNode *L,*p,*q;
int i;
//先建立一个带头节点的单链表
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
q=L; //q的初始值指向头节点
for(i=0; i<=n-1; i++)
{
p=(LNode *)malloc(sizeof(LNode)); /*生成新节点*/
printf("请输入第%d个元素的值:",i);
scanf("%d",&p->data);//输入元素值
p->next=NULL;q->next=p;q=p;//将该节点插入到表尾
}
return L;
}
插入操作
//在带头节点的单链表L中第i个位置之前插入元素e,若插入成功则返回1,否则返回0
int Insert_LinkList (LinkList L, inti,ElemType e)
{
LNode *p,*s;
int j;
p=L; j=-1;
while(p&&j<i-1)
{p=p->next;j++;}//寻找第i-1个节点
if(!p || j>i-1)
return0; //i值不合法
s=(LNode *)malloc(sizeof(LNode));//生成新节点
s->data=e;
s->next=p->next; p->next=s;//实现插入
return 1;
}
删除操作
//在带头节点的单链表L中,删除第i个元素,并由e返回其值,若删除成功,则返回1,否则返回0
int Delete_LinkList (LinkList L, inti,ElemType *e)
{
LNode *p,*q;
int j;
p=L; j=-1;
//寻找第i个节点,并令p指向其前驱
while(p->next &&j<i-1)
{ p=p->next; j++; }
//删除位置不合理
if(!(p->next)||j>i-1)
return 0;
q=p->next;
*e=q->data; //用e返回被删节点数据域的值
p->next=q->next;
free(q); //删除并释放节点
return 1;
}
求单链表的表长(长度不是从0开始)
int Length_LinkList1(LinkList L)//当链表带头节点时
{
LNode *p=L;//p指向头节点
int i=0;//设计数器变量i
while(p->next) //p指针依次后移
{ p=p->next; i++; }
return i;
}
按位查找
//在带头节点的单链表L中查找第i个元素,若成功则返回该节点,否则返回空
LNode *Get_LinkList(LinkList L,int i)
{
LNode *p=L; //p指向单链表L的头节点
int j=-1;
while(p->next!=NULL&&j<i)
{
p=p->next;
j++;
}
if(j==i) return p;
else return NULL;
}
按值查找
//在带头节点的单链表L中查找与给定值相同的元素的位序,若成功则返回该节点,否则返回-1
int Locate_LinkList(LinkList L,ElemType e)
{
LNode *p=L->next; //p指向单链表L的最前面的节点
int i=0;
while(p!=NULL&&p->data!=e)
{
p=p->next;i++;
}
if(p->data==e)
return i;
else
return -1;
}
双向链表
链表结构
typedef struct DuLNode{
ElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode,*DuLinkList;
插入操作
//设L为双向循环链表的节点,在地址为p的节点之后插入地址为s的新节点
void inselem(DuLinkList L,ElemType e,DuLNode p)
{
DuLNode s,r;
s=(DuLNode)malloc(sizeof(DuLNode));
s->data=e; //建立一个新节点s
r=p->next;
s->next=r;
r->prior=s; //插在节点p之后
p->next=s;
s->prior=p;
}
删除操作
//设L为双向循环链表的头节点,删除地址为p的节点
void delelm(DuLinkList L, DuLNode p)
{
DuLNode q,r;
q=p->prior;
r=p->next;
q->next=r;
r->prior=q;
free(p);
}