1.线性表
一个线性表是由有限个类型相同的数据元素组成。在这有限个数据元素中,数据元素构成一个有序的序列,除了第一个元素和最后一个元素外,其他元素有唯一的前驱元素和唯一的后继元素。
数据元素可以是原子类型,也可以是复合类型。
线性表主要分为两种,顺序存储结构和链式存储结构。
2.顺序存储的线性表
顺序存储的线性表的数据域:
#define ListSize 100//建立线性表的长度
typedef int MyType;//建立自己的线性表想使用的类型
typedef struct
{
MyType list[ListSize];//数据存储部分
int length;//表示线性表当前长度
}SeqList;//线性表本体
线性表的初始化:
void InitList(SeqList *l)//线性表的初始化
{
l->length = 0;
}
判断线性表是否为空:
int ListEmpty(SeqList *l)//判断线性表是否为空
{
if(l->length==0)
return 1;//如果线性表为空则返回1
else
return 0;
}
为线性表指定位置插入元素:
int InsertList(SeqList *l,int i,MyType e)//往线性表里插入数据
{
int j;
if(i<1||i>l->length+1)
{
cout<<"您要插入的位置不合法!"<<endl;
return -1;//返回值-1表示操作不合法
}
else if(l->length==ListSize)
{
cout<<"线性表已满!"<<endl;
return 0;//返回值0表示无法插入
}
else
{
if(l->length==0)
{
l->list[0] = e;
l->length++;
return 1;
}
for(j=l->length;j>=i;j--)
{
l->list[j] = l->list[j-1];
}
l->list[j] = e;
l->length++;
return 1;//返回值1表示插入成功
}
}
按内容查找线性表:
int LocateElem(SeqList l,MyType e)//按内容查找
{
int i;
for(i=0;i<l.length;i++)
if(l.list[i]==e)
return i+1;
return 0;
}
按位置查找:
int GetElem(SeqList *l,int i,MyType *e)//按位置查找
{
if(i<1||i>l->length+1)
{
cout<<"您要查找的位置不合法!"<<endl;
return -1;//返回值-1表示操作不合法
}
*e = l->list[i-1];//将找到的元素放进变量e中
return 1;//返回1表示找到
}
删除指定元素:
int DeleteList(SeqList *l,int i,MyType *e)//删除指定元素
{
int j;
if(l->length<=0)
{
cout<<"空列表无法完成删除操作"<<endl;
return 0;
}
else if(i<1||i>l->length)
{
cout<<"删除位置不合法!"<<endl;
return -1;
}
else
{
*e = l->list[i-1];
for(j=i;j<l->length;j++)
{
l->list[j-1] = l->list[j];
}
l->length--;
return 1;
}
}
返回线性表的长度 :
int ListLength(SeqList l)//返回线性表的长度
{
return l.length;
}
清空线性表:
void ClearList(SeqList *l) //清空线性表
{
l->length = 0;
}
显示全部线性表 :
void PrintList(SeqList *l) //显示全部线性表
{
for(int i=0;i<l->length;i++)
cout<<l->list[i]<<" ";
cout<<endl;
}
3.链式存储的线性表——链表
typedef int DataType;
typedef struct Node
{
DataType data;//数据域(车厢运货的部分)
struct Node *next;//指针域(连接车厢的挂钩)
}ListNode,*LinkList;//ListNode是链表每个节点的类型,LinkList是指向链表节点的指针
LinkList L;//表示定义了一个链表。L实际是指向火车头
头结点(火车头的意思)
如果不带头结点链表,L = NULL;表示空链表
带头结点的链表,L->next = NULL;表示空链表
初始化链表:
void InitList(LinkList *head)//初始化链表 (本质是初始化火车头)
{
if((*head=(LinkList)malloc(sizeof(ListNode)))==NULL)//如果内存分配失败
exit(-1);//以错误结束程序
(*head)->next = NULL;//链表头(火车头)先为空
}
判断链表是否为空:
int ListEmpty(LinkList head)//判断链表是否为空
{
if(head->next==NULL)
return 1;//如果为空返回1,否则返回0
else
return 0;
}
按序号查找链表的节点:
ListNode *Get(LinkList head,int i)//按序号查找,找到链表里的第几个元素
{
ListNode *p;
int j;
if(ListEmpty(head))//要判断待查找的链表不能为空
return NULL;
if(i<1)//要查找的序号不能有误
return NULL;
j = 0;
p = head;
while(p->next!=NULL&&j<i)
{
p=p->next;
j++;
}
if(j==i)
return p;//成功返回指向该节点的指针
else
NULL:
}
ListNode *LocateElem(LinkList head,DataType e)//按内容查找
{
ListNode *p;
p = head->next;
while(p)
{
if(p->data!=e)
p=p->next;
else
break;
}
return p;
}
int LocatePos(LinkList head,DataType e)//定位
{
ListNode *p;
int i;
if(ListEmpty(head))
return 0;
p=head->next;
i=1;
while(p)
{
if(p->data==0)
return 1;
else
{
p=p->next;
i++;
}
}
if(!p)
return 0;
}
int InsertList(LinkList head,int i,DataType e)//插入
{
ListNode *p,*pre;
int j;
pre = head;
j=0;
while(pre->next!=NULL&&j<i-1)
{
pre=pre->next;
j++;
}
if(j!=i-1)
{
cout<<"插入位置错!"<<endl;
return 0;
}
if((p=(ListNode *)malloc(sizeof(ListNode)))==NULL)
exit(-1);
p->data=e;
p->next=pre->next;
pre->next = p;
return 1;
}
int DeleteList(LinkList head,int i,DataType *e)//删除指定位置的函数
{
ListNode *pre,*p;
int j;
pre = head;
j = 0;
while(pre->next!=NULL&&pre->next->next!=NULL&&j<i-1)
{
pre=pre->next;
j++;
}
if(j!=i-1)
{
cout<<"删除位置错误"<<endl;
return 0;
}
p=pre->next;
*e=p->data;
pre->next=p->next;
free(p);
return 1;
}
int ListLength(LinkList head)//返回链表长度
{
ListNode *p;
int count = 0;
p = head;
while(p->next!=NULL)
{
p=P->next;
count++;
}
return count;
}
void DestroyList(LinkList head)//销毁链表
{
ListNode *p,*q;
p = head;
while(p!=NULL)
{
q=p;
p=p->next;
free(q);
}
}
循环单链表:指最后一个节点(车厢)的next指向车头head
双向链表:每个节点都有两个指针,一个指向前面,一个指向后面
4.栈
#define StackSize 100
typedef int DataType;
typedef struct
{
DataType stack[StackSize];
int top;
} SeqStack;
void InitStack(SeqStack *S)//初始化栈
{
S->top = 0;
}
int StackEmpty(SeqStack S)//判断栈是否为空
{
if(S.top==0)
return 1;
else
return 0;
}
int GetTop(SeqStack S,DataType *e)//取出一个元素
{
if(S.top<=0)
{
cout<<"栈为空"<<endl;
return 0;
}
else
{
*e = S.stack[S.top-1];
return 1;
}
}
int PushStack(SeqStack *S,DataType e)//进栈操作
{
if(S->top>=StackSize)
{
cout<<"栈已满"<<endl;
return 0;
}
else
{
S->stack[S->top] = e;
S->top++;
return 1;
}
}
int PopStack(SeqStack *S,DataType *e) //出栈操作
{
if(S->top==0)
{
cout<<"栈为空"<<endl;
return 0;
}
else
{
S->top--;
*e = S->stack[S->top];
return 1;
}
}
int StackLength(SeqStack S)//返回栈长度
{
return S.top;
}
void ClearStack(SeqStack *S)//清空栈
{
S->top = 0;
}
int main()
{
SeqStack zhan;
InitStack(&zhan);//初始化栈
return 0;
}
5.队列
#define QueueSize 100
typedef int DataType;
typedef struct Squeue{
DataType queue[QueueSize];
int front,rear;
}SeqQueue;
void InitQueue(SeqQueue *SQ)//初始化队列
{
SQ->front = SQ->rear = 0;
}
int QueueEmpty(SeqQueue SQ)//判断列表是否为空
{
if(SQ.front==SQ.rear)
return 1;
else
return 0;
}
int EnterQueue(SeqQueue *SQ,DataType x)//入队操作
{
if(SQ->rear==QueueSize)
return 0;
SQ->queue[SQ->rear] = x;
SQ->rear++;
return 1;
}
int DeteleQueue(SeqQueue *SQ,DataType *e)//出队操作
{
if(SQ->front==SQ->rear)//判断是否为空
return 0;
else
{
*e = SQ->queue[SQ->front];
SQ->front++;
return 1;
}
}
int main()
{
SeqQueue dl;
InitQueue(&dl);
if(QueueEmpty(dl))
cout<<"队列暂时为空"<<endl;
EnterQueue(&dl,5);
int a;
DeteleQueue(&dl,&a);
cout<<a<<endl;
return 0;
}
6.树
树的结点:包含一个数据元素以及若干指向子树分支的信息。
结点的度:一个结点拥有子树的个数称为结点的度。
叶子结点:也称为终端结点,没有子树的结点也就是度为零的结点称为叶子结点。
分支结点:也称作非终端结点,度不为零的结点称为非终端结点。
孩子结点:一个结点的子树的根结点称为孩子结点。
双亲结点:也称为父节点,如果一个结点存在孩子结点,则该结点就称为孩子结点的双亲结点或者父结点。
子孙结点:在一个根节点的子树中的任何一个结点都称为该结点的子孙结点。
祖先结点:从根节点开始到达一个结点,所经过的所有分支结点,都称为该结点的祖先结点。
兄弟结点:一个双亲结点的所有孩子结点之间互相称作兄弟结点。
树的度:树中所有结点的度的最大值。
树的层次:从根节点开始,根节点为为第一层,根节点的孩子结点为第二层,以此类推,如果某一结点是第L层,则其他孩子结点位于第L+1层。
树的深度:也成为树的高度,树中所有结点的层次最大值称为树的深度。
有序树:如果树中各个子树的次序是有先后次序的,则称该树为有序树。
无序树:如果树中各个子树的次序是没有有先后次序的,则称该树为无序树。
森林:m课互不相交的树构成一个森林。
二叉树:一个结点最多有两个孩子结点。
满二叉树:每层结点都是满的称为满二叉树。
完全二叉树:如果一棵二叉树有n个结点,并且二叉树的n个结点的结构与满二叉树的前n个结点结构完全相同,则称这样的二叉树为完全二叉树。
二叉树的性质:
(1)在二叉树中,第m(m>=1)层上至多有2的m-1次方个结点(规定根节点为第一层)。
(2)深度为k(k>=1)的二叉树中至多有2的k次方减1个结点。
(3)对于任何一棵二叉树T,如果叶子结点总数为n0,度为2的结点总数为n2。,则有n0=n2+1
(4)如果完全二叉树有n个结点,则深度为不大于log以2为底n的对数的最大整数加1。
(5)如果完全二叉树有n个结点,按照从上到下,从左到右的顺序对二叉树对二叉树中的每个结点从1到n进行编号,则对于任意结点i有以下性质:
a.如果i=1,则序号i对应的结点就是根结点,该结点没有双亲结点。如果i>1,则序号为i的结点的双亲结点的序号为不大于i/2的最大整数;
b.如果2*i>n,则序号为i的结点没有左孩子结点;如果2*i<=n,则序号为i的结点的左孩子结点序号为2*i。
c.如果2*i+1>n,则序号为i的结点没有右孩子结点。如果2*i+1<=n,则序号为i的结点的右孩子结点的序号为2*i+1。
typedef int DataType;
typedef struct Node
{
struct Node *leftchild;//指向左孩子结点
struct Node *rightchild;//指向右孩子结点
DataType data;//数据域
}*BitTree,BitNode;
void InitBitTree(BitTree *T)//初始化二叉树
{
*T = NULL;
}
void DestroyBitTree(BitTree *T)//销毁(删除)二叉树
{
if(*T)//二叉树是否为空
{
if((*T)->leftchild)
DestroyBitTree(&(*T)->leftchild);
if((*T)->rightchild)
DestroyBitTree(&(*T)->rightchild);
free(*T);
*T = NULL;
}
}
void CreateBitTree(BitTree *T) //创建二叉树
{
DataType ch;
cin>>ch;
if(ch==0)
*T = NULL;
else
{
*T = (BitTree)malloc(sizeof(BitTree));
if(!(*T))
exit(-1);
(*T)->data = ch;
CreateBitTree(&(*T)->leftchild);
CreateBitTree(&(*T)->rightchild);
}
}
int InsertLeftChild(BitTree p,BitTree c)//二叉树的左插入操作
{
if(p)
{
c->rightchild = p->leftchild;
p->leftchild = c;
return 1;
}
return 0;
}
int InsertRightChild(BitTree p,BitTree c)//二叉树的右插入操作
{
if(p)
{
c->rightchild = p->rightchild;
p->rightchild = c;
return 1;
}
return 0;
}
BitTree Point(BitTree T,DataType e)//返回二叉树结点指针的操作
{
BitTree Q[MaxSize];// MaxSize大小自己定义
int front=0,rear=0;
BitNode *p;
if(T)
{
Q[rear]=T;
rear++;
while(front!=rear)
{
p=Q[front];
front++;
if(p->data==e)
return p;
if(p->leftchild)
{
Q[rear++]=p->leftchild;
}
if(p->rightchild)
{
Q[rear++]=p->rightchild;
}
}
}
return NULL;
}
DataType LeftChild(BitTree T,DataType e)//返回二叉树的结点的左孩子元素值操作
{
BitTree p;
if(T)
{
p = Point(T,e);
if(P&&P->leftchild)
return p->leftchild->data;
}
return ;
}
DataType RightChild(BitTree T,DataType e)//返回二叉树的结点的右孩子元素值操作
{
BitTree p;
if(T)
{
p = Point(T,e);
if(P&&P->rightchild)
return p->rightchild->data;
}
return ;
}
int DeleteLeftChild(BitTree p) //二叉树的左删除操作
{
if(p)
{
DestroyBitTree(&(p->leftchild));
return 1;
}
return 0;
}
int DeleteRightChild(BitTree p) //二叉树的左删除操作
{
if(p)
{
DestroyBitTree(&(p->rightchild));
return 1;
}
return 0;
}
int main()
{
BitTree T;
InitBitTree(&T);
return 0;
}
二叉树的遍历:
(1)先序遍历:
a.访问根结点
b.先序遍历左子树
c.先序遍历右子树
(2)中序遍历:
a.中序遍历左子树
b.访问根结点
c.中序遍历右子树
(3)后序遍历
a.后序遍历左子树
b.后序遍历右子树
c.访问根结点