第二章 线性表
线性表是n个数据元素的有限序列,在稍复杂的线性表中,一个数据元素可以由若干个数据项(item)组成,在这种情况下,常把数据元素称为记录(record),含有大量记录的线性表称为文件(file)。
线性表的基本函数:
typedef int Status;
typedef int ElemType;
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ERROR 0
#define OK 1
#define INFEASIBLE -1
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0
typedef struct
{
ElemType* elem;
int length;
int listSize;
}Sqlist;
//数组指针elem指示线性表的基地址,length指示线性表的当前长度,顺序表的初始化操作就是为顺序表分配一个预定义大小的数组空间,并将线性表的当前长度设为“0”
Status InitList(Sqlist& L)
{
L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!L.elem) exit(OVERFLOW);
L.length = 0;
L.listSize = LIST_INIT_SIZE;
return OK;
}
Status DestroyList(Sqlist& L)
{
free(L.elem);
return OK;
}
Status ClearList(Sqlist& L)
{
if (!L.elem) exit(OVERFLOW);
L.length = 0;
return OK;
}
Status ListEmpty(Sqlist L)
{
if (!L.elem) exit(OVERFLOW);
if (L.length == 0) return TRUE;
else return FALSE;
}
int ListLength(Sqlist L)
{
return L.length;
}
int GetElem(Sqlist L, int i, ElemType& e)
{
if (i<1 || i>L.length - 1) return ERROR;
e = L.elem[i - 1];
return OK;
}
int LocateElem(Sqlist L, ElemType e, Status(*compare)(ElemType, ElemType))
{
ElemType *p;
int i=1;
p = L.elem;
while (i <= L.length && !(*compare)(*p++, e))
++i;
if (i <= L.length)
return i;
else
return 0;
}
Status compare(ElemType c1, ElemType c2)
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
Status PriorElem(Sqlist L, ElemType cur_e, ElemType& pre_e)
{
int i;
ElemType* p, * q;
p = &(L.elem[0]);
for (i = 1; i < L.length - 1; i++)
{
if (cur_e == L.elem[i]) { p = &L.elem[i]; break; }
}
q = p - 1;
pre_e = *q;
return pre_e;
}
Status NextElem(Sqlist L, ElemType cur_e, ElemType& next_e)
{
int i;
ElemType* p, * q;
p = &(L.elem[0]);
for (i = 0; i < L.length-1; i++)
{
if(cur_e == L.elem[i]) { p = &L.elem[i]; break; }
}
q = p + 1;
next_e = *q;
return next_e;
}
Status ListInsert(Sqlist& L, int i, ElemType e)
{
ElemType* newbase, * p, * q;
if (i<1 || i>L.length + 1) return ERROR;
if (L.length >= L.listSize)
{
newbase = (ElemType*)realloc(L.elem, (L.listSize + LISTINCREMENT) * sizeof(ElemType));
if (!newbase) exit(OVERFLOW);
L.elem = newbase;
L.listSize += LISTINCREMENT;
}
q = &(L.elem[i - 1]);
for (p = &(L.elem[L.length - 1]); p >= q; --p)
*(p + 1) = *p;
*q = e;
++L.length;
return OK;
}
Status ListDelete(Sqlist& L, int i, ElemType& e)
{
ElemType* p, * q;
if (i<1 || i>L.length) return ERROR;
p = &(L.elem[i - 1]);
e = *p;
q = L.elem + L.length - 1;
for (++p; p <= q; ++p)
*(p - 1) = *p;
--L.length;
return OK;
}
Status ListTraverse(Sqlist L, void(*vi)(ElemType*))
{
int i;
ElemType* p;
p = L.elem;
for (i = 1; i <= L.length; i++) vi(p++);
printf("\n");
return OK;
}
void visit(ElemType* e)
{
printf("%5d", *e);
}
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。(物理相邻,逻辑相邻)
typedef int Status;
typedef int ElemType;
#define ERROR 0
#define OK 1
#define INFEASIBLE -1
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0
typedef struct LNode//结点类型
{
int data;
LNode* next;
}*Link, * Position;
typedef struct//链表类型
{
Link head, tail;
int len;
}LinkList;
Status MakeNode(Link& p, int e)
{
p = (Link)malloc(sizeof(LNode));//由系统生成一个LNode型的结点,同时将该结点的起始位置赋给指针变量p
if (!p) exit(OVERFLOW);
p->data = e;
p->next = NULL;
return OK;
}
Status FreeNode(Link& p)
{
free(p);
return OK;
}
Status InitList(LinkList& L)
{
L.head = (Link)malloc(sizeof(LNode));
if (!L.head) return FALSE;
L.tail = L.head;
L.head->next = NULL;
L.len = 0;
return OK;
}
Status DestroyList(LinkList& L)
{
LNode* p = L.head;
while (p)
{
LNode* q = p;
p = p->next;
free(q);
}
L.tail = L.head = NULL;
return OK;
}
Status ClearList(LinkList& L)
{
LNode* p = L.head->next;
while (p)
{
LNode* q = p;
p = p->next;
free(q);
}
L.tail = L.head;
L.len = 0;
L.head->next = NULL;
return OK;
}
Status InsFirst(Link h, Link s)
{
s->next = h->next;
h->next = s;
return OK;
}
Status DelFirst(Link h, Link& q)
{
q = h->next;
h->next = h->next->next;
free(q);
return OK;
}
Status Append(LinkList& L, Link s)
{
L.tail->next = s;
while (L.tail->next)
{
L.tail = L.tail->next;
L.len++;
}
return OK;
}
Status Remove(LinkList& L, Link& q)
{
LNode* s = L.head;
while (s->next != L.tail)
{
s = s->next;
}
q = L.tail;
L.tail = s;
s->next = NULL;
L.len--;
return OK;
}
Status InsBefore(LinkList& L, Link& p, Link s)
{
LNode* q = L.head;
while (q->next != p)
{
q = q->next;
}
s->next = p;
q->next = s;
L.len++;
return OK;
}
Status InsAfter(LinkList& L, Link& p, Link s)
{
s->next = p->next;
p->next = s;
p = s;
L.len++;
return OK;
}
Status SetCurElem(Link& p, int e)
{
p->data = e;
return OK;
}
ElemType GetCurElem(Link p)
{
return p->data;
}
Status ListEmpty(LinkList L)
{
if (L.len == 0) return OK;
else return FALSE;
}
int ListLength(LinkList L)
{
return L.len;
}
Position GetHead(LinkList L)
{
return L.head;
}
Position GetLast(LinkList L)
{
return L.tail;
}
Position PriorPos(LinkList L, Link p)
{
LNode* s = L.head;
while (s->next != p)
{
s = s->next;
}
if (s == L.head)
{
return NULL;
}
return s;
}
Position NextPos(LinkList L, Link p)
{
return p->next;
}
Status LocatePos(LinkList L, int i, Link& p)
{
int j = 1;
LNode* s = L.head->next;
if (i < 1 || i > L.len) return ERROR;
while (s && j < i)
{
s = s->next;
j++;
}
if (!s || j > i)
{
return ERROR;
}
p = s;
return OK;
}
Position LocateElem(LinkList L, int e, bool(*compare)(int, int))
{
LNode* s = L.head->next;
while (s)
{
if (compare(s->data, e))
{
return s;
}
}
return NULL;
}
Status ListTraverse(LinkList L, void(*visit)(Link))
{
LNode* s = L.head->next;
while (s)
{
visit(s);
s = s->next;
}
return OK;
}
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素。数据元素ai存储其本身的信息(数据域)之外,还存储一个指示其直接后继的的位置(指针域),这两部分信息组成数据元素ai的存储映像,称为结点(node)。整个链表的存取从头指针开始进行,头指针指示链表的第一个结点的存储位置;链表最后一个结点的指针为空(NULL)