线性表:
ADT
ADT 线性表(List)
Data
线性表的数据对象集合为{a1,a2,…,an},每个元素的类型均为DataType。
其中,
除第一个元素a1外,每一个元素有且只有一个直接前驱元素,
除了最后一个元素an外,每一个元素有且只有一个直接后继元素。
数据元素之间的关系是一对一的关系。
Operation
InitList(*L): 初始化操作,建立一个空的线性表L
ListEmpty(L): 判断线性表是否为空表,若线性表为空,返回true,否则返回false
ClearList(*L): 将线性表清空
GetElem(L,i,*e): 将线性表L中的第i个位置元素值返回给e
LocateElem(L,e): 在线性表L中查找与给定值e相等的元素,如果查找成功,返回该元素在表中序号表示成功;否则,返回0表示失败
ListInsert(*L,i,e): 在线性表L中第i个位置插入新元素e
ListDelete(*L,i,*e): 删除线性表L中第i个位置元素,并用e返回其值
ListLength(L): 返回线性表L的元素个数
endADT
DEMO
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);
}
}
}
顺序存储
- 第 i 个数据元素 ai 的存储位置可以由 a1 推算得出:LOC(ai) = LOC(a1) + (i-1)*c
- 【随机存取】:可以随时计算出线性表中任意位置的地址
- 存取O(1)
- 插入、删除O(n)
存储结构
#define MAXSIZE 20
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int length;
} SqList;
GetElem
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
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;
}
ListInsert
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if( L->length == MAXSIZE )
{
return ERROR;
}
if( i<1 || i>L->length+1)
{
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;
}
ListDelete
Status ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if( L->length == 0 )
{
return ERROR;
}
if( i<1 || i>L->length )
{
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;
}
链式存储
- 结点:【数据域】 + 【指针域】
- 第一个结点的存储位置叫做头指针,最后一个结点指针为空(NULL)
- 存取 O(n)
- 插入、删除 O(1)
头指针:
- 头指针是指链表指向第一个结点的指针,若链表有头结点,则是【指向头结点的指针】
- 头指针具有标识作用,所以常用头指针冠以链表的名字(指针变量的名字)
- 无论链表是否为空,头指针均不为空
头节点:
- 头结点是为了操作的统一和方便而设立的,放在第一个元素的结点之前,其数据域一般无意义(但也可以用来存放链表的长度)
- 有了头结点,对在第一元素结点前插入结点和删除第一结点起操作与其它结点的操作就统一了
单链表
存储结构
typedef struct Node
{
ElemType data;
struct Node *Next;
} Node;
typedef struct Node *LinkList;
GetElem
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;
}
ListInsert
Status ListInsert(LinkList *L, int i, ElemType e)
{
int j;
LinkList p, s;
p = *L;
j = 1;
while( p && j<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;
}
ListDelete
Status ListDelete(LinkList *L, int i, ElemType *e)
{
int j;
LinkList p, q;
p = *L;
j = 1;
while( p->next && j<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;
}
CreateListHead
void CreateListHead(LinkList *L, int n)
{
LinkList p;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
(*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;
}
}
CreateListTail
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;
}
ClearList
Status ClearList(LinkList *L)
{
LinkList p, q;
p = (*L)->next;
while(p)
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL;
return OK;
}
静态链表
- 用数组描述的链表
- 存储结构是链式存储
- 【备用链表】:未被使用的数组元素
- 【数组一个元素】:存放备用链表第一个结点下标
- 【数组最后元素】:存放第一个插入元素的下标,链表为空存放0
存储结构
#define MAXSIZE 1000
typedef struct
{
ElemType data;
int cur;
} Component, StaticLinkList[MAXSIZE];
InitList
Status InitList(StaticLinkList space)
{
int i;
for( i=0; i < MAXSIZE-1; i++ ){
space[i].cur = i + 1;
}
space[MAXSIZE-1].cur = 0;
return OK;
}
ListInsert
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;
if( space[0].cur ){
space[0].cur = space[i].cur;
}
return i;
}
Status ListInsert( StaticLinkList L, int i, ElemType e )
{
int j, k, l;
k = MAX_SIZE - 1;
if( i<1 || i>ListLength(L)+1 )
{
return ERROR;
}
j = Malloc_SLL(L);
if( j )
{
L[j].data = e;
for( l=1; l <= i-1; l++ )
{
k = L[k].cur;
}
L[j].cur = L[k].cur;
L[k].cur = j;
return OK;
}
return ERROR;
}
ListDelete
Status ListDelete(StaticLinkList L, int i)
{
int j, k;
if( i<1 || i>ListLength(L) )
{
return ERROR;
}
k = MAX_SIZE - 1;
for( j=1; j <= i-1; j++ )
{
k = L[k].cur;
}
j = L[k].cur;
L[k].cur = L[j].cur;
Free_SLL(L, j);
return OK;
}
void Free_SLL(StaticLinkList space, int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
ListLength
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE-1].cur;
while(i)
{
i = L[i].cur;
j++;
}
return j;
}
循环链表
- 带尾指针(rear)的循环链表 查找终端结点\开始结点 O(1)
存储结构
typedef struct CLinkList
{
int data;
struct CLinkList *next;
}node;
ds_init
void ds_init(node **pNode)
{
int item;
node *temp;
node *target;
printf("输入结点的值,输入0完成初始化\n");
while(1)
{
scanf("%d", &item);
fflush(stdin);
if(item == 0)
return;
if((*pNode) == NULL)
{
*pNode = (node*)malloc(sizeof(struct CLinkList));
if(!(*pNode))
exit(0);
(*pNode)->data = item;
(*pNode)->next = *pNode;
}
else
{
for(target = (*pNode); target->next != (*pNode); target = target->next)
;
temp = (node *)malloc(sizeof(struct CLinkList));
if(!temp)
exit(0);
temp->data = item;
temp->next = *pNode;
target->next = temp;
}
}
}
ds_insert
void ds_insert(node **pNode , int i)
{
node *temp;
node *target;
node *p;
int item;
int j = 1;
printf("输入要插入结点的值:");
scanf("%d", &item);
if(i == 1)
{
temp = (node *)malloc(sizeof(struct CLinkList));
if(!temp)
exit(0);
temp->data = item;
for(target = (*pNode); target->next != (*pNode); target = target->next)
;
temp->next = (*pNode);
target->next = temp;
*pNode = temp;
}
else
{
target = *pNode;
for( ; j < (i-1); ++j )
{
target = target->next;
}
temp = (node *)malloc(sizeof(struct CLinkList));
if(!temp)
exit(0);
temp->data = item;
p = target->next;
target->next = temp;
temp->next = p;
}
}
ds_delete
void ds_delete(node **pNode, int i)
{
node *target;
node *temp;
int j = 1;
if(i == 1)
{
for(target = *pNode; target->next != *pNode;target = target->next)
;
temp = *pNode;
*pNode = (*pNode)->next;
target->next = *pNode;
free(temp);
}
else
{
target = *pNode;
for( ; j < i-1; ++j)
{
target = target->next;
}
temp = target->next;
target->next = temp->next;
free(temp);
}
}
ds_search
int ds_search(node *pNode, int elem)
{
node *target;
int i = 1;
for(target = pNode; target->data != elem && target->next != pNode; ++i)
{
target = target->next;
}
if(target->next == pNode)
return 0;
else
return i;
}
带尾指针的循环链表的合并
LinkList Connect(LinkList A,LinkList B)
{
LinkList p = A->next;
A->next = B->next->next;
free(B->next);
B->next = p;
return B;
}
双向链表
存储结构
typedef struct DualNode
{
ElemType data;
struct DualNode *prior;
struct DualNode *next;
} DualNode, *DuLinkList;
插入
s->prior = p;
s->next = p->next;
p->next->prior = s;
p->next = s;
删除
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);