数据结构笔记

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.访问根结点

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值