关于线性表的一些基本操作,以及如何利用线性表实现栈和队列
线性表是n个性质相同的数据元素的有限序列。
在复杂的线性表中,一个数据元素可以由若干个数据项组成。其中常把数据元素称为记录,含有大量记录的线性表又称文件。
线性表的十二种基本操作:
(对线性表内部元素有改变时加&符号)
1、InitList(&L)
操作结果:构造一个空的线性表L。
Status InitList(SqList &L)
{
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
//申请存储空间
if(!L.elem)
exit(0);
L.length=0;//空表的长度为0
L.list=LIST_INT_SIZE;//初始数据元素存储容量
return OK;
}//InitList
2、DestroyList(&L)
初始条件:线性表L已存在
操作结果:销毁线性表L。
Status Destroy(SqList &L)
{
free(L.elem);
L.elem=NULL;
L.length=0;
L.listsize=0;
return OK;
}//Destroy
3、ClearList(&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
Status ClearList(SqList &L)
{
L.length=0; //令线性表的长度为零
return OK;
}
4、ListEmpty(L)
初始条件:线性表L已存在
操作结果:若L为空表,则返回TRUE,否则返回FALSE。
bool ListEmpty(SqList L)
{
if(L.length == 0)
return TRUE;
else
return FALSE;
}
5、ListLength(L)
初始条件:线性表L已存在。
操作结果:返回L中数据元素个数
int ListLength(SqList L)
{
return L.length;
}
6、GetElem(L, i, &e)
初始条件:线性表L已存在,1<=i<=ListLength(L)。
操作结果:用e返回L中第i个数据元素的值
Status GetElem(SqList L,int i, ElemType &e)
{
e=*(L.elem+i-1);
return OK;
}
7、LocateElem(L, e, compare())
初始条件:线性表L已存在,compare()是数据元素判定函数
操作结果:返回L中第一个与e满足关系compare()的数据元素的位序。若这样的元素不存在,则返回值为0。
int LocateElem(SqList L,ElemType e,status(*compare)(ElemType,ElemType))
{
Elem *p=L.elem;
int i=1;
while(i<=L.length&&!compare(*p++,e))//在线性表长度内且未找到第一个满足条件的元素
{
if(i<=L.length)
return i;
else
return 0;
}
8、PriorElem( L, cur_e, &pre_e)
初始条件:线性表L已存在
操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义。
Status PriorElem(SqList L,ElemType cur_e,ElemType &pre_e)
{
int a;
a=LocateElem(L,cur_e,equal);
if(!a||a==1){
cout<<"查找失败"<;
return error;
}
pre_e=*(L.elem+a-2);
return OK;
}
9、NextElem(L, cur_e, &next_e)
初始条件:线性表L已存在
操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回他的后继,否则操作失败,next_e无定义。
Status NextElem(SqList L,ElemType cur_e,ElemType &next_e)
{
int a;
a=LocateElem(L,cur_e,equal);
if(!a||a==L.length){
cout<<"查找失败"<;
return error;
}
next_e=*(L.elem+a);
return OK;
}
10、ListInsert(&L, i, e)
初始条件:线性表L已存在,1<=i<=ListLength(L) + 1
操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加一。
Status ListInsert(SqList &L,int i,ElemType e)
{
ElemType *newbase,*q,*p;
if(L.length>=L.listsize){ //当前存储空间已满,增加分配
if(!(newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType))))
exit(0);//分配存储空间失败
L.elem=newbase;//新基址
L.listsize+=LISTINREMENT;//增加存储容量
}
q=L.elem+i-1;//q为插入位置
for(p=L.elem+L.length-1;p>=q;--p) {
*(p+1)=*p;//给插入位置之后的元素赋值达到之后元素后移一位的效果
}
*q=e;//插入e
++L.length;
return OK;
}
11、ListDelete(&L, i, e)
初始条件:线性表L已存在且非空,1<=i<=ListLength(L)
操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减一
Status ListDelete(SqList &L,int i,ElemType &e)
{
ElemType *p,*q;
if(i<1||i>L.length)//i值不合法
return error;
p=L.elem+i-1;//p为被删除元素的位置
e=*p;//被删除元素的值赋给e
q=L.elem+L.length-1;//表尾元素的位置
for(++p;p<=q;++p)
*(p-1)=*p;
L.length--;
return OK;
}
12、ListTraverse(L,visit())
初始条件:线性表L已存在
操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。
Status ListTraverse(SqList L, void(*visit)(ElemType&))
{
ElemType *p=L.elem;
int i;
for(i=1;i<=L.length;i++)
visit(*p++);
cout<return OK;
}
栈是限定仅在表尾进行插入或删除操作的线性表。表尾称为栈顶,表头称为栈底。不含元素的空表成为空栈。
//定义节点
typedef struct data{
int value;
struct data *next;
}node;
//定义栈
typedef struct _stack {
node *top;
node *bottom;
size_t num;
}stack;
//构建空栈
void init(stack *s)
{
s->top = NULL;
s->bottom = NULL;
s->num = 0;
}
//判断栈内元素
status StackEmpty(stack *s)
{
if(s->n == 0)
return 0;
else
return 1;
}
//栈顶
int top(stack *s)
{
if (StackEmpty(s) == 1) {
return s->top->data;
} else {
printf("stack is empty\n");
return 0;
}
}
//出栈
void pop(stack *s)
{
node *tmp;
if (StackEmpty(s) == 1) {
tmp = s->top;
s->top = tmp->next;
free(tmp);
s->num--;
if (StackEmpty(s) == 1) {
s->bottom = NULL;
}
} else {
printf("stack is empty\n");
}
}
//入栈
void push(stack *s, int data)
{
node *pdata = (node *)malloc(sizeof(node));
pdata->data = data;
if (StackEmpty(s) == 0) {
s->top = pdata;
s->bottom = pdata;
pdata->next = NULL;
} else {
pdata->next = s->top;
s->top = pdata;
}
s->num++;
}
//清空栈
void clear_stack(stack *s)
{
while (StackEmpty(s) == 1) {
pop(s);
}
}
和栈相反,队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端删除元素。
//定义节点
typedef struct data{
int value;
struct data *next;
}node;
//定义队列
typedef struct _queue{
node *front;
node *rear;
size_t num;
}queue;
//构建空队列
void init(queue *q)
{
q->top = NULL;
q->bottom = NULL;
q->num = 0;
}
//判断栈内元素
status QueueEmpty(queue *q)
{
if(q->n == 0)
return 0;
else
return 1;
}
//进列
void push(queue *q, int val)
{
node *pnode = (node*)malloc(sizeof(node));
pnode->data = val;
pnode->next = NULL;
if (q->rear) {
q->rear->next = pnode;
} else {
q->front = pnode;
}
q->rear = pnode;
q->num++;
}
//出列
void pop(queue *q)
{
if (QueueEmpty(q) == 1) {
node *pnode = q->front;
q->front = q->front->next;
free(pnode);
q->num--;
if (QueueEmpty(q) == 0) {
q->rear = NULL;
}
} else {
printf("error: pop the empty queue");
}
}
//清空列
void clear_queue(queue *q)
{
while (QueueEmpty(q) == 1) {
pop(q);
}
}