constants.h
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1//不可实行的
#define OVERFLOW -2//溢出
typedef int Status;
线性表的顺序存储结构
Sqlist.h
#include "constants.h"
#define LIST_INIT_SIZE 20 //顺序表存储空间的初始分配量
#define LISTINCREMENT 5 //顺序表存储空间的分配增量
typedef int ElemType;
typedef struct
{
ElemType *elem; //存储空间的基地址
int length; //顺序表的当前长度
int listsize; //数组存储空间的长度
} Sqlist;
Status InitList(Sqlist &L); //构造一个空的线性表L
Status ListEmpty(Sqlist L); //判断线性表L是否是空表,若是,则返回TRUE,否则返回FALSE
int ListLength(Sqlist L); //返回线性表L的长度
Status GetElem(Sqlist L, int i, ElemType &e); //用e返回线性表L的第i个数据元素的值
int LocateElem(Sqlist L, ElemType e, Status (*compare)(ElemType, ElemType)); //在线性表L中查找第一个和元素e满足compare关系的元素,若找到则返回其位序;否则返回0
Status PriorElem(Sqlist L, ElemType e, ElemType &pre_e); //用pre_e返回线性表L中元素e的直接前驱
Status NextElem(Sqlist L, ElemType e, ElemType &next_e); //用next_e返回线性表L中元素e的直接后继
Status ListInsert(Sqlist &L, int i, ElemType e); //将数据元素e插入到线性表L的第i个数据元素之前
Status ListDelete(Sqlist &L, int i, ElemType &e); //删除线性表L的第i个数据元素,并将其值用e返回
Status ListTraverse(Sqlist L, Status (*visit)(ElemType)); //依次对线性表L中的每个元素调用visit进行访问
Status ClearList(Sqlist &L); //重置线性表L为空表
Status DestroyList(Sqlist &L); //销毁线性表L,可能的话释放其空间
Status adjust(Sqlist &L);
Status compare_equal(ElemType a, ElemType b);
Status visit_read(ElemType a);
void MergeList_Sq(Sqlist L1, Sqlist L2, Sqlist &l0);
Sqlist.cpp
#include "sqlist.h"
#include<stdlib.h>
#include<stdio.h>
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 ListEmpty(Sqlist L)
{
if (!L.length)
return TRUE;
else
return FALSE;
}
int ListLength(Sqlist L)
{
return L.length;
}
Status GetElem(Sqlist L, int i, ElemType &e)
{
if (i > 0 && i <= L.length)
{
e = L.elem[i - 1];
return OK;
}
else
return ERROR;
}
//函数做参数 用指针来表达(与数组类似)
//在调用时参数只需要写函数名,在使用时也只需要写函数名
int LocateElem(Sqlist L, ElemType e, Status (*compare)(ElemType, ElemType))
{
int i = 1;
ElemType *p = L.elem;
/* 前缀递增递减和*优先级相同,从右到左;
后缀递增递减比前缀优先级高,从左到右。 */
while (i <= L.length && !compare(e, *p++))
i++;
if (i > L.length)
return 0;
else
return i;
}
Status PriorElem(Sqlist L, ElemType e, ElemType &pre_e)
{
int weixu = LocateElem(L, e, compare_equal);
if (weixu > 1)
{
pre_e = L.elem[weixu - 2];
return OK;
}
else
return ERROR;
}
Status NextElem(Sqlist L, ElemType e, ElemType &next_e)
{
int weixu = LocateElem(L, e, compare_equal);
if (weixu > 0 && weixu < L.length)
{
next_e = L.elem[weixu];
return OK;
}
else
return ERROR;
}
//把元素e插入到第i个元素前面 <==> 让元素e成为顺序表中的第i个元素
Status ListInsert(Sqlist &L, int i, ElemType e)
{
if (i < 1 || i > L.length + 1)
return ERROR;
else
{
if (L.length == L.listsize)
if (!adjust(L))
exit(OVERFLOW);
ElemType *p = L.elem + L.length - 1;
while (p != L.elem + i - 2)
{
*(p + 1) = *p;
p--;
}
*(p + 1) = e;
/* ElemType *p = &L.elem[i - 1], *q;
for (q = &L.elem[L.length - 1]; q >= p; q--)
*(q + 1) = *q;
*q = e; */
L.length++;
return OK;
}
}
//在ListInsert和ListDelete函数的最后一定要记得更新L。length的值
Status ListDelete(Sqlist &L, int i, ElemType &e)
{
if (i < 1 || i > L.length)
return ERROR;
else
{
e = L.elem[i - 1];
ElemType *p = &L.elem[i], *q = &L.elem[L.length - 1];
for (; p <= q; p++)
*(p - 1) = *p;
/* ElemType *p = L.elem + i - 1, *q = L.elem + L.length - 1;
e = *p;
for (p++; p <= q; p++)
*(p + 1) = *p; */
L.length--;
return OK;
}
}
Status ListTraverse(Sqlist L, Status (*visit)(ElemType))
{
ElemType *p, *q = L.elem + L.length - 1;
for (p = L.elem; p <= q; p++)
if (!visit(*p))
return ERROR;
return OK;
}
Status ClearList(Sqlist &L)
{
L.length = 0;
return OK;
}
//free函数调用之前需要加一个if句来判断将要free的指针是否指向某一块内存空间,free之后赋值为NULL
Status DestroyList(Sqlist &L)
{
if (L.elem)
free(L.elem);
L.elem = NULL;
return OK;
}
/* 原型:extern void *realloc(void *mem_address, unsigned int newsize);
语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。
//新的大小若小于原来的大小,原数据的末尾可能丢失(被其他使用内存的数据覆盖等)
头文件:#include <stdlib.h> 有些编译器需要#include <malloc.h>,在TC2.0中可以使用alloc.h头文件
功能:先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
注意:这里原始内存中的数据还是保持不变的。当内存不再使用时,应使用free()函数将内存块释放。 */
Status adjust(Sqlist &L)
{
L.elem = (ElemType *)realloc(L.elem, (LIST_INIT_SIZE + LISTINCREMENT) * sizeof(ElemType));
if (!L.elem)
exit(OVERFLOW);
else
{
L.listsize += LISTINCREMENT;
return OK;
}
}
Status compare_equal(ElemType a, ElemType b)
{
return a == b ? TRUE : FALSE;
}
Status visit_read(ElemType a)
{
printf("%d\n", a);
return OK;
}
void MergeList_Sq(Sqlist L1, Sqlist L2, Sqlist &L0)
{
ElemType *p1 = L1.elem, *p2 = L2.elem;
L0.listsize = L0.length = L1.length + L2.length;
ElemType *p0 = (ElemType*)malloc(L0.length*sizeof(ElemType));
L0.elem = p0;
ElemType *p1_last = L1.elem + L1.length - 1, *p2_last = L2.elem + L2.length - 1;
while (p1 <= p1_last && p2 <= p2_last)
{
if (*p1 < *p2)
*p0++ = *p1++;
else
*p0++ = *p2++;
}
while (p1 <= p1_last)
*p0++ = *p1++;
while (p2 <= p2_last)
*p0++ = *p2++;
/* L0.elem = (ElemType *)malloc((L1.length + L2.length) * sizeof(ElemType));
L0.length = L1.length + L2.length;
L0.listsize = L0.length;
int i = 0, j = 0, k = 0;
while (i < L1.length && j < L2.length)
{
if (L1.elem[i] < L2.elem[j])
L0.elem[k++] = L1.elem[i++];
else
L0.elem[k++] = L2.elem[j++];
}
if (i == L1.length)
while (j < L2.length)
L0.elem[k++] = L2.elem[j++];
else
while (i < L1.length)
L0.elem[k++] = L1.elem[i++]; */
}
线性表的链式存储结构
单链表(最简单)
LinkList.h
#include "constants.h"
typedef int ElemType;
//Attention: *结构体类型要有名字 *typedef之后的别名可以和原名一样
typedef struct LNode
{
ElemType data; //数据域
struct LNode *next; //指针域
} LNode, *LinkList;
Status InitList(LinkList &L); //构造一个空的线性表L
Status ListEmpty(LinkList L); //判断线性表L是否是空表,若是,则返回TRUE,否则返回FALSE
int ListLength(LinkList L); //返回线性表L的长度
Status GetElem(LinkList L, int i, ElemType &e); //用e返回线性表L的第i个数据元素的值
LNode *LocateElem(LinkList L, ElemType e, Status (*compare)(ElemType, ElemType)); //在线性表L中查找第一个和元素e满足compare关系的元素,若找到则返回其位序;否则返回0
Status PriorElem(LinkList L, ElemType e, ElemType &pre_e); //用pre_e返回线性表L中元素e的直接前驱
Status NextElem(LinkList L, ElemType e, ElemType &next_e); //用next_e返回线性表L中元素e的直接后继
Status ListInsert(LinkList &L, int i, ElemType e); //将数据元素e插入到线性表L的第i个数据元素之前
Status ListDelete(LinkList L, int i, ElemType &e); //删除线性表L的第i个数据元素,并将其值用e返回
Status ListTraverse(LinkList L, Status (*visit)(ElemType)); //依次对线性表L中的每个元素调用visit进行访问
Status ClearList(LinkList &L); //重置线性表L为空表
Status DestroyList(LinkList &L); //销毁线性表L,可能的话释放其空间
Status compare_equal(ElemType a, ElemType b);
Status visit_read(ElemType a);
void MergeList_LinkList(LinkList L1, LinkList L2, LinkList &l0);
void CreateList_backward(LinkList &L, int n);//逆向建立n个元素的单链表
LinkList.cpp
#include "Linklist.h"
#include <stdio.h>
#include <stdlib.h>
Status InitList(LinkList &L) //O(1)
{
L = (LinkList)malloc(sizeof(LNode));
if (!L)
exit(OVERFLOW);
L->next = NULL;
return OK;
}
Status ListEmpty(LinkList L) //O(1)
{
/* return L->next ? TRUE : FALSE; */
if (!L->next)
return TRUE;
else
return FALSE;
}
int ListLength(LinkList L) //O(n)
{
LNode *p = L->next;
int length = 0;
while (p)
{
length++;
p = p->next;
}
return length;
}
Status GetElem(LinkList L, int i, ElemType &e) //O(n)
{
/* if (i < 1 || i > ListLength(L))
return ERROR;
LNode *p = L;
int j;
for (j = 0; j < i; j++)
p = p->next;
e = p->data;
return OK; */
int j = 1;
LNode *p = L->next;
while (p && j < i)
{
p = p->next;
j++;
}
if (!p || j > i)
return ERROR;
else
{
e = p->data;
return OK;
}
}
/* 定位函数不准返回ERROR 因为ERROR是int类型 不是LNode*类型
找到即返回该结点的地址 找不到即返回NULL */
LNode *LocateElem(LinkList L, ElemType e, Status (*compare)(ElemType, ElemType)) //O(n)
{
LNode *p = L->next;
while (p && !compare(e, p->data))
p = p->next;
return p;
}
Status PriorElem(LinkList L, ElemType e, ElemType &pre_e)
{
LNode *p = L->next;
while (p && p->next->data != e)
p = p->next;
if (!p)
return ERROR;
else
{
pre_e = p->data;
return OK;
}
}
Status NextElem(LinkList L, ElemType e, ElemType &next_e)
{
LNode *p = LocateElem(L, e, compare_equal);
if (!p && !p->next)
return ERROR;
else
{
next_e = p->data;
return OK;
}
}
Status ListInsert(LinkList &L, int i, ElemType e)
{
if (i < 1 || i > ListLength(L) + 1)
return ERROR;
else
{
LNode *p=L;
int j;
for (j = 0; j < i - 1; j++)
p = p->next;
LNode *p0 = (LNode *)malloc(sizeof(LNode));
if (!p0)
exit(OVERFLOW);
else
{
p0->data = e;
p0->next = p->next;
p->next = p0;
return OK;
}
}
}
void CreateList_backward(LinkList &L, int n)
{
InitList(L);
while (n--)
{
int x;
scanf("%d",&x);
ListInsert(L, 1, x);
}
}
//删除过后的结点需要被释放内存
Status ListDelete(LinkList &L, int i, ElemType &e)
{
if (i < 1 || i > ListLength(L))
return ERROR;
else
{
LNode *p = L;
int j;
for (j = 0; j < i - 1; j++)
p = p->next;
e = p->next->data;
free(p->next);
p->next = p->next->next;
return OK;
}
}
Status ListTraverse(LinkList L, Status (*visit)(ElemType))
{
LNode *p = L->next;
while (p)
{
if (!visit(p->data))
return ERROR;
p = p->next;
}
return OK;
}
//clear函数思想:不断free(L->next)
Status ClearList(LinkList &L)
{
LNode *p;
for (p = L->next; p; p = L->next)
{
L->next = p->next;
free(p);
}
return OK;
}
Status DestroyList(LinkList &L)
{
while (L)
{
LNode *p = L->next;
free(L);
L = p;
}
return OK;
}
Status compare_equal(ElemType a, ElemType b)
{
return a == b ? TRUE : FALSE;
}
Status visit_read(ElemType a)
{
printf("%d\n", a);
return OK;
}
void MergeList_LinkList(LinkList L1, LinkList L2, LinkList &L0)
{
LNode *p1 = L1->next, *p2 = L2->next, *p = L0;
while (p1 && p2)
{
LNode *p0 = (LNode *)malloc(sizeof(LNode));
p->next = p0;
p0->next = NULL;
if (p1->data < p2->data)
{
p0->data = p1->data;
p1 = p1->next;
}
else
{
p0->data = p2->data;
p2 = p2->next;
}
p = p->next;
}
while (p1)
{
LNode *p0 = (LNode *)malloc(sizeof(LNode));
p->next = p0;
p0->next = NULL;
p0->data = p1->data;
p1 = p1->next;
p = p->next;
}
while (p2)
{
LNode *p0 = (LNode *)malloc(sizeof(LNode));
p->next = p0;
p0->next = NULL;
p0->data = p2->data;
p2 = p2->next;
p = p->next;
}
}