一、栈
栈实现的是一种后进先出(last-in,first-out,LIFO)策略,在栈中被删除的都是最近插入的元素。
栈上的insert操作被称为压入(PUSH),而无元素参数的DELETE操作被称为弹出(POP)。
我们简单地用定长的数组来实现栈:
#include <cstdlib>
#include <iostream>
using namespace std;
struct MyStack
{
int mSet[100];
int mLen;
};
void InitStack(MyStack &s)
{
s.mLen=0;
}
bool IsEmpty(MyStack &s)
{
if(s.mLen==0)
{
return true;
}
else
{
return false;
}
}
void Push(MyStack &s,int item)
{
if(s.mLen==100)
return;
s.mSet[s.mLen]=item;
s.mLen++;
}
int Pop(MyStack &s)
{
if(IsEmpty(s))
{
return -1;
}
s.mLen--;
return s.mSet[s.mLen];
}
int Peek(MyStack s){
if(IsEmpty(s))
{
return -1;
}
return s.mSet[s.mLen-1];
}
void PrintStack(MyStack s)
{
for(int i=0;i<s.mLen;i++)
{
cout<<s.mSet[i]<<"\t";
}
cout<<"\n";
}
int main(int argc, char *argv[])
{
MyStack s;
InitStack(s);
Push(s,23);Push(s,35);
Push(s,11);Push(s,46);Push(s,78);
PrintStack(s);
Pop(s);Push(s,99);
PrintStack(s);
system("PAUSE");
return EXIT_SUCCESS;
}
除了定长数组之外,我们还可以用动态数组或者链表来实现栈的结构。采用动态数组来实现,我们只需要变更一下struct的结构,如下:
struct MyStack
{
int *mSet; //指向动态数组的指针
int mSize; //栈可用大小
int mLen; //当前栈元素个数
};
剩下的就是在栈空间不足的时候,重新申请数组,复制数组内容,释放原有数组空间。
二、队列
在队列中,被删去的总是在集合中存在时间最长的那个元素,队列实现的是先进先出(first-in,first-out,FIFO)的策略。
队列上的insert操作被称为入队(ENQUEUE),delete操作被称为出队(DEQUEUE)。
队列中有队头和队尾,我们采用定长数组来实现队列,head指向队头元素,tail指向下一个元素将要插入的位置。
#include <cstdlib>
#include <iostream>
using namespace std;
struct MyQueue
{
int mSet[100];
int mHead; //队列头元素的位置
int mTail; //下一个元素将要插入的位置
int mLen; //队列中元素的个数
};
void InitQueue(MyQueue &q)
{
q.mLen=0;
q.mHead=0;
q.mTail=0;
}
void EnQueue(MyQueue &q,int item)
{
if(q.mLen==100)
return;
q.mSet[q.mTail]=item;
q.mTail=(q.mTail+1)%100;
q.mLen++;
}
int DeQueue(MyQueue &q)
{
if(q.mLen==0)
return -1;
int r=q.mSet[q.mHead];
q.mHead=(q.mHead+1)%100;
q.mLen--;
return r;
}
void PrintQueue(MyQueue q)
{
for(int i=0;i<q.mLen;i++)
{
int index=(q.mHead+i)%100;
printf("%d\t",q.mSet[index]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
MyQueue q;
InitQueue(q);
EnQueue(q,3);EnQueue(q,48);EnQueue(q,37);
EnQueue(q,62);EnQueue(q,1);EnQueue(q,15);
PrintQueue(q);
DeQueue(q);
EnQueue(q,99);
PrintQueue(q);
system("PAUSE");
return EXIT_SUCCESS;
}
队列也可以采用动态数组和链表的形式来实现,这里不再赘述。
三、链表
链表中的各对象按照线性顺序排列,链表的顺序由各个对象的指针决定。
我们先看下单链接链表的实现:
#include <cstdlib>
#include <iostream>
using namespace std;
struct mNode
{
int mData;
struct mNode * next;
};
void PrintList(mNode *h)
{
struct mNode *p=h;
while(p!=0)
{
printf("%d\t",p->mData);
p=p->next;
}
printf("\n");
}
void InsertTail(mNode *&h,int item)
{
struct mNode *pNew=new struct mNode;
pNew->mData=item;
pNew->next=0;
if(h==0)
{
h=pNew;
return;
}
struct mNode *p=h;
while(p->next!=0)
{
p=p->next;
}
p->next=pNew;
}
void InsertAfter(mNode *&h,int item1,int item2)
{
struct mNode *pNew=new struct mNode;
pNew->mData=item2;
struct mNode *p=h;
while(p!=0)
{
if(p->mData==item1)
{
pNew->next=p->next;
p->next=pNew;
}
p=p->next;
}
}
bool DeleteElem(mNode *&h,int item)
{
if(h==0)
{
return false;
}
if(h->mData==item)
{
h=h->next;
return true;
}
mNode *p=h;
mNode *q=p->next;
while(q!=0)
{
if(q->mData==item)
{
p->next=q->next;
delete q;
return true;
}
p=p->next;
q=q->next;
}
return false;
}
int main(int argc, char *argv[])
{
struct mNode *node1=new struct mNode;
struct mNode *node2=new struct mNode;
node1->mData=32;
node2->mData=14;
node1->next=node2;
node2->next=0;
PrintList(node1);
InsertTail(node1,45);
InsertAfter(node1,14,26);
PrintList(node1);
DeleteElem(node1,26);
PrintList(node1);
system("PAUSE");
return EXIT_SUCCESS;
}
如果链表是双向链接的,则也只是多出一个prev指针,指向对象的前驱元素。在循环链表中,表头元素的prev指针指向表尾元素,表尾元素的next指针指向表头元素。