目录
一、顺序表
顺序表是线性表的顺序存储,通过一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。假定线性表的元素类型为ElemType,则线性表的顺序存储类型描述为:
//静态分配
#define MaxSize 50
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int length;
}SqList;
C语言中一维数组可以进行动态分配避免溢出;
(1)插入操作
bool ListInsert(SqList &L,int i,ElemType e){
//在顺序表L的第i(1<=i<=L.length+1)个位置插入新元素e
if(i<1 || i>L.length+1)
return false;
if(L.length>=MaxSize)
return false;
for(int j=L.length;j>=i;j--) //将第i个元素及之后的元素后移
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
(2)删除操作
bool ListDelete(SqList &L,int i, ElemType &e){
//删除顺序表L中第i个未知的元素
if(i<1 || i>L.length)
return false;
e=L.data[i-1];
for(int j=i;j<L.length;j++)
L.data[j-1]=L.data[j];
L.length--;
return true;
}
(3)按值查找
bool LocateElem(SqList &L,ElemType e){
//查找顺序表中值为e的元素,查找成功则返回元素位置,否则返回0
int i;
for(int i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1;
return 0;
}
二、单链表
单链表是线性表的链式存储,通过一组任意的储存单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表节点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。单链表中的节点类型如下:
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode, *LinkList;
通常用头指针来标识一个单链表,此外为了操作上的方便,在单链表第一个节点之前附加一个结点,称为头结点。
(1)建立单链表
LinkList CreatList1(LinkList &L){
//头插法建立单链表
LNode *s;int x;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
scanf("%d",&x);
while(x!=9999){
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
LinkList CreatList2(LinkList &L){
//尾插法建立单链表
int x;
L=(LinkList)malloc(sizeof(LNode));
LNode *s,*r=L;
scanf("%d",&x);
while(x!=9999){
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return L;
}
(2)按序号查找节点值
LNode *GetElem(LinkList L,int i){
//取出单链表L(带头节点)中第i个位置的结点指针
int j=1;
LNode *p=L->next;
if(i==0)
return L;
if(i<1)
return NULL;
while(p&&j<i){
p=p->next;
j++;
}
return p;
}
(3)按值查找表结点
LNode *LocateElem(LinkList L,ElemType e){
//查找单链表L(带头结点)中数据值等于e的结点指针,否则返回NULL
LNode *p=L->next;
while(p!=NULL&&p->data!=e)
p=p->next;
return p;
}
(4)插入结点
bool ListFrontInsert(LinkList L,int i,ElemType e){
//将值为x的新节点插入到单链表的第i个位置桑
LinkList p=GetElem(L,i-1);
if(NULL==p){
return false;
}
LinkList s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
三、双向链表
双向链表在单链表的基础上增加了一个指向其前驱的prior指针,结点类型及相关函数描述如下:
typedef int ElemType;
typedef struct DNode{
ElemType data;
struct DNode *prior,*next;
}DNode,*DLinkList;
DLinkList Dlist_head_insert(DLinkList &DL){
//头插法
DNode *s;int x;
DL=(DLinkList)malloc(sizeof(DNode));
DL->next=NULL;
DL->prior=NULL;
scanf("%d",&x);
while(x!=9999){
s=(DNode*)malloc(sizeof(DNode));
s->data=x;
s->next=DL->next;
if(DL->next!=NULL){
DL->next->prior=s;
}
s->prior=DL;
DL->next=s;
scanf("%d",&x);
}
return DL;
}
DLinkList Dlist_tail_insert(DLinkList &DL){
//尾插法
int x;
DL=(DLinkList)malloc(sizeof(DNode));
DNode *s,*r=DL;
DL->prior=NULL;
scanf("%d",&x);
while(x!=9999){
s=(DNode*)malloc(sizeof(DNode));
s->data=x;
r->next=s;
s->prior=r;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return DL;
}
DNode *GetElem(DLinkList DL,int i){
//返回第i个位置的结点指针
int j=1;
DNode *p=DL->next;
if(i==0)
return DL;
if(i<1)
return NULL;
while(p&&j<i){
p=p->next;
j++;
}
return p;
}
bool DListFrontInsert(DLinkList DL,int i,ElemType e){
//插入结点
DLinkList p=GetElem(DL,i-1);
if(NULL==p){
return false;
}
DLinkList s=(DNode*)malloc(sizeof(DNode));
s->data=e;
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
bool DListDelete(DLinkList DL,int i){
//删除第i个结点
DLinkList p=GetElem(DL,i-1);
if(NULL==p){
return false;
}
DLinkList q;
q=p->next;
if(q==NULL)
return false;
p->next=q->next;
if(q->next!=NULL){ //删除最后一个元素,需要的判断
q->next->prior=p;
}
free(q);
return true;
}
三、顺序栈
顺序栈是采用顺序存储的栈,它利用一组地址连续的储存单元存放自栈底到栈顶的数据元素,同时设一个指针top指示当前栈顶位置。
//实现栈 可以用数组,也可以用链表
#define MaxSize 50
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];
int top;
}SqStack;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}*LiStack;
void InitStack(SqStack &S){
//初始化
S.top=-1;
}
bool StackEmpty(SqStack &S){
//栈判空
if(S.top==-1)
return true;
else
return false;
}
bool Push(SqStack &S,ElemType x){
//进栈
if(S.top==MaxSize-1){
return false;
}
S.data[++S.top]=x;
return true;
}
bool Pop(SqStack &S,ElemType &x){
//出栈
if(-1==S.top)
return false;
x=S.data[S.top--];
return true;
}
bool GetTop(SqStack &S,ElemType &x){
//读取栈顶元素
if(-1==S.top)
return false;
x=S.data[S.top];
return true;
}
四、循环队列
循环队列是将顺序队列臆造为一个环状空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。
顺序队列结点类型描述如下:
//队列可以用数组也可用链表实现
#define MaxSize 5
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
void InitQueue(SqQueue &Q) {
//初始化
Q.rear=Q.front=0;
}
bool isEmpty(SqQueue &Q) {
//判队空
if(Q.rear==Q.front)
return true;
else
return false;
}
bool EnQueue(SqQueue &Q,ElemType x){
//入队
if((Q.rear+1)%MaxSize==Q.front)
return false;
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
return true;
}
bool DeQueue(SqQueue &Q,ElemType &x){
//出队
if(Q.rear==Q.front)
return false;
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
return true;
}
链式队列描述如下:
typedef int ElemType;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front,*rear;
}LinkQueue;
void InitQueue(LinkQueue &Q){
//初始化
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
bool IsEmpty(LinkQueue &Q){
//判队空
if(Q.front==Q.rear)
return true;
else
return false;
}
void EnQueue(LinkQueue &Q,ElemType x){
//入队
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;s->next=NULL;
Q.rear->next=s;
Q.rear=s;
}
bool DeQueue(LinkQueue &Q,ElemType &x){
//出队
if(Q.front==Q.rear) return false;
LinkNode *p=Q.front->next;
x=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return true;
}
五、二叉树
//链式存储
typedef struct BiNode
{
char data;
struct BiTNode *lchild,*rchild;
}BiNode,*BiTree;
//前中后序遍历
void Inorder(BiTree T){
if(T == NULL) return ;
Inorder(T->lchild);
// visit(T->data);
printf("%c ", T->data);
Inorder(T->rchild);
}
void preorder(BiTree T){
if(T == NULL) return ;
// visit(T->data);
printf("%c ", T->data);
Inorder(T->lchild);
Inorder(T->rchild);
}
void postorder(BiTree T){
if(T == NULL) return ;
Inorder(T->lchild);
Inorder(T->rchild);
// visit(T->data);
printf("%c ", T->data);
}
//层次遍历
void leverorder(BiTree BT){
InitQueue(Q);
BiTree P;
EnQueue(Q,BT);
while(!IsEmpty(Q){
DeQueue(Q,P);
visit(P);
if(p->lchild!=NULL)
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)
EnQueue(Q,p->rchild);
}
}
}
//非递归
void inorder(BiTree T){
InitStack(S);
BiNode *p = T;
while(!StackEmpty(S) || p){
if(!p) {
Push(S, p);
p = p->lchild;
}else {
Pop(S, p);
printf("%c ", p->data);
p = p->rchild;
}
}
}
void postorder(BiTree T){
InitStack(S);
BiNode *p = T, *last = NULL;
while(!StackEmpty(S) || p){
if(p){
Push(S, p);
p = p->lchild;
}
else {
GetTop(S, p);
if(p->rchild && p == last){ // 向右子树 递归
Pop(S, p);
printf("%c ", p->data);
last = p;
p = NULL;
}else {
p = p->rchild;
}
}
}
}