您的位置:首页 > 理论基础 > 数据结构算法

数据结构

2016-08-10 11:56 225 查看
一、线性表
1、顺序存储=============
类型定义:
const Maxsize=100;
typedef struct
{
DataType data[Maxsize];
int length;
}SeqList;
SeqList L;

相关操作实现
1)插入
//在顺序表的第i个节点前插入节点值为x新节点
void InsertSeqList(SeqList L,int i,DataType x)
{
if(L.length==Maxsize) exit "表已满"
if(i<1||i>L.length+1) exit "位置错"
else
for(int j=L.length;j>=i;j--)
{
L.data[j]=L.data[j-1];
}
L.data[i-1]=x;
L.length++;
}
----------------------------------------
2)删除
void DeleteSeqList(SeqList L,int i)
{
if(i<1||i>L.length) exit "非法位置"
else
for(int j=i;j<L.length;j++)
{
L.data[j-1]=L.data[j];
}
L.length--;

}

-----------------------------------------
3)定位
//在顺序表中查找值为x的节点序号,找不到返回0
int LocateSeqList(SeqList L,DataType x)
{
int i=0;
while(i<L.length && L.data[i] !=x)
{
i++;
}
if(i<L.length) return i+1;
else return 0;
}

2、链式存储=============
类型定义:
typedef struct node
{
DataType data;
struct node * next;
}Node,*LinkList,
-----------------------------
1)初始化
LinkList InitiateLinkList()
{
LinkList head;
head=malloc(sizeof(Node));
head->next=NULL;
return head;
}
-----------------------------
2)求表长
int LengthLinkList(LinkList head)
{
LinkList p = head;
int cnt=0;
while(NULL != p->next)
{
p=p->next;
cnt++;
}
return cnt;
}

-----------------------------
3)读表元素
//在链表中找第i个元素的节点,找到返回指向该节点的指针,找不到返回NULL
LinkList GetLinkList(LinkList head,int i)
{
LinkList p = head->next;
int c=1;
while((NULL != p) && (c < i))
{
c++;
p=p->next;
}
if(c == i)
{
retrun p;
}
else retrun NULL;
}

-----------------------------
4)定位
//在表head中查找值为x的节点序号,找不到返回0
int LocateLinkList(LinkList head,DateType x)
{
LinkList p = head->next;
int c=1;
while(NULL != p && p->data !=x)
{
p=p->next;
c++;
}
if(NULL != p) return c;
else return 0;
}

5)插入
//在链表第i个节点前插入新节点数值为x,(指针q指向插入节点的前一个节点,p指向新生成的节点)
void InsertlinkList(LinkList head,int i,DataType x)
{
LinkList * p, *q;
if(1==i) q=head;
else q=GetLinkList(LinkList head,int i-1); //找到第i-1个数据元素结点,单链表插入时必须找到插入节点的前一个节点
if(NULL = q)
{
exit "找不到合法插入位置"
}
else
{
p=malloc(sizeof(Node));
p->data=x; //给新节点赋值
p->next=q->next;
q->next=p;

}

}

6)删除
//删除表第i个节点(指针q指向删除节点的前一个节点,p指向删除节点)
void DeletelinkList(LinkList head,int i)
{
LinkList * p, *q;
if(1==i) q=head;
else q=GetLinkList(LinkList head,int i-1); //找到第i-1个数据元素结点
if(NULL != q && NULL != q->next)
{
p=q->next;
q->next=p->next;
free(p);
}
else
exit "删除的节点不存在"
}

建表操作(三种方法)
方法一:

方法二:
//尾插法,每次向表尾插入新的节点,设置指针q一直指向尾节点,设备指针t指向新生成的节点
LinkList CreateLinkList()
{
Linklist head; //定义头指针变量
Node *q,*t;
int x;
head = malloc(sizeof(Node));//生成头节点
q=head; //尾指针首先指向头节点
scanf("%d",&x); //读取第一个元素
while(x !=0)
{
t=malloc(sizeof(Node));
t->data=x;
q->next=t;
q=t; //修改尾指针,让其指向新的尾节点
scanf("%d",&x); //读取新的元素
}
q->next = NULL;
return head;

}

方法三:
//头插法,每次向表头插入新的节点,设置指针p指向新生成的节点
LinkList CreateLinkList()
{
Linklist head; //定义头指针变量
Node *p;
int x;
head = malloc(sizeof(Node));//生成头节点
head->next=NULL; //初始时,首节点为空
scanf("%d",&x); //读取第一个元素
while(x)
{
p=malloc(sizeof(Node));
p->data = x;
p->next=head->next; //第一个加入的节点将成为尾节点q->next=NULL;
head->next=q;
scanf("%d",&x); //读取新的元素
}
return head;

}

3、循环链表
1)删除
2)插入

----------------------------
----------------------------
//将一个带头结点的链表逆转
LinkList * reverse(LinkList *L)
{
LinkList * p,*q;
p=L->next;
L->next=NULL;
while(p!=NULL)
{
q=p;
p=p->next;
q->next=L->next; //用头插入法
L->next=q;
}
retrun L;
}

----------------------------
----------------------------
//计算头指针为head的单链表中值为X的个数
int count(LinkList head,DataType x)
{
int cnt = 0;
LinkList p = head;
while(NULL!=p)
{
if(x==p->data)
cnt++;
p=p->next;
}
retrun cnt;
}

二、栈、队列、数组
(一)栈,一种运算受限的线性表,操作只能在表的一端,具有先进后出的特点
======================================================
顺序实现:
数据类型定义:
const init maxsize=10;
typedef struct seqstack;
{
DataTye data[maxisze];
int top //标识栈顶位置的变量
}SeqStk;

基本运算如下:
1、初始化
int InitStack(SeqStk * stk)
{
stk->top=0;
return 1;
}

2、判断空
int EmptyStack(SeqStk * stk)
{
if(stk->top==0);
return 1;
else return 0;
}

3、进栈
int PushStack(SeqStk * stk,DataType x)
{
if(stk->top==maxsize-1);
{
error("栈已满") return 0;
}
else
{
stk->top++;
stk->data[stk-top]=x;
return 1;
}
return 1;
}
4、出栈
int PopStack(SeqStk * stk)
{
if(EmptyStack(stk))
{
error("下溢") return 0;
}
else
{
stk->top--;
return 1
}
}

5、取元素
int GetStack(SeqStk * stk)
{
if(EmptyStack(stk))
{
retrun NULLdata;
}
else
{
return stk->data[stk->top];
}
}

====================================
链式实现
数据类型定义:
typedef struck node
{
DataType data;
struck node * next;
}LkStk;
//链栈可以用一个带头结点的链表来实现

基本运算:
1、初始化
void InitStack(LKStk * LS)
{
LS=(LKStk *)malloc(sizeof(LKStk)); //生成头节点
LS->next=NULL; //头节点NEXT为空
}

2、判断空
int EmptyStack(LKStk * LS)
{
if(LS->next=NULL);
return 1;
else return 0;
}

3、进栈
void PushStck(LKStk * LS,DataType x)
{
LKSst * temp;
temp=(LKStk *)malloc(sizeof(LKStk));
temp->data=x;
temp->next=LS->next;
LS-next=temp;
}

4、出栈
int PopStck(LKStk * LS)
{
if(!EmptyStack)
{
LKStk * temp;
temp=LS->next;
LS-next=temp-next;
free(temp);
return 1
}
else return 0
}

5、取栈顶元素
DateType GetTop(LKStk * LS)
{
if(!EmptyStack)
{
return LS->next->data;
}
else return NULLdata;
}

(2)队列
顺序实现,它由一个一维数组及两个分别指示队列首和队列尾的变量组成,
两个变量分别称为“队列首指针”和“队列尾指针”
循环队列数据类型定义:
const int maxsize=6;
typedef struck cycqueue
{
DataType data[maxsize];
int front,rear;
}Cycque;
Cycque CQ;

循环队列满条件:(CQ.rear+1)%maxsize == CQ.front
循环队列空条件:CQ.rear == CQ.front

循环队列的设计,利用模运算
入队:rear=(rear+1)%maxsize
出队:front=(front+1)%maxsize

基本运算:
1、初始化
void Initcycqueue(Cycque CQ)
{
CQ.front=0
CQ.rear=0
}

2、判断空
int Emptyqueue(Cycque CQ)
{
if(CQ.rear == CQ.front)
return 1;
else return 0;
}

3、入队列
int Enqueue(Cycque CQ,DataType x)
{
if((CQ.rear+1)%maxsize == CQ.front)
{
error("队列满");return 0;
}
else
{
CQ.rear=(CQ.rear+1)%maxsize;
CQ.data[CQ.rear]=x;
return 1;
}
}

4、出队列
int Outqueue(Cycque CQ)
{
if(Emptyqueue(CQ))
{
error("队列空");return 0;
}
else
{
CQ.front=(CQ.front+1)%maxsize;
return 1;
}
}

5、取队列首元素
DataType Gethead(Cycque CQ)
{
if(Emptyqueue(CQ))
{
return NULLdata;
}
else
{
return CQ.data[(CQ.front+1)%maxsize];

}
}

=====================================
队列的链接实现
//用一个带头结点的链表来表示队列,称为链队列
//头指针指向头结点,头结点的next指向首结点,尾指针指向队列尾结点
数据类型定义:
typedef struct LinkQueueNode
{
DataType data;
struck LinkQueueNode * next;
}LkQueNode;

typedef struct LKQueue
{
LkQueNode *front *rear;
}LKQue;
LKQue LQ;

基本运算:
1、队列初始化
void InitQueue(LKQue LQ)
{
LKQueNode *temp;
temp = (LKQueNode *)malloc(sizeof(LkQueNode))
LQ->front = temp;
LQ->rear = temp;
LQ->rear->next = NULL;
}

2、判断空
int Emptyqueue(LKQue LQ)
{
if(CQ->rear == CQ->front)
return 1;
else return 0;
}

3、入队列
void Enqueue(LKQue LQ,DataType x)
{
LKQueNode * temp;
temp = (LkQueNode *)malloc(sizeof(LkQueNode));
temp->data=x;
temp->next=NULL;
(LQ->rear)->next=temp;
LQ->rear=temp;

}

4、出队列
int Outqueue(LKQue LQ)
{
LKQueNode * temp;
if(Emptyqueue(LQ))
{
error("队列空")
return 0;
}
else
{
temp = (LQ->front)->next; //使temp指向队列的首节点
LQ->front->next=temp->next;//使头结点指针指向新的首结点
if(temp->next==NULL)
LQ->front=LQ->rear; //无首节点时
free(temp);
return 1;
}
}

5、取队列首元素
DataTye Getqueue(LKQue LQ)
{
LKQueNode * temp;
if(Emptyqueue(LQ))
{
return NULLdata;
}
else
{
temp=LQ.front->next;
return temp->data;
}
}

三、树和二叉树
1)基本概念:
结点的度:树上任一结点拥有的子树的数目称为该结点的度。
树的度:一棵树中所有结点的度的最大值称该结的度。
结点的层次:从根开始算起,根的层次为1,其余结点的层次为其双亲的层次加1.
树的高度:一棵树中所有结点层次数的最大值为该树的高度或深度。

二叉树的性质:
1.二叉树的第i层上至多有2 i-1个结点
2.深度为K的二叉树至多有2的K次方-1个结点
3.叶子结点n0,度为2的结点为n2,则n0=n2+1
4.n个结点的完全二叉绔的深度为

二叉对的存储结构:
1、

2、链式存储结构

二叉树的数据类型定义:
typedef struct btnode
{
DataType data;
struct btnode lchild,*rchild;
}*BinTree;

2)二叉树的遍历
2.1)二叉树遍历的递归实现
2.1.1)先序遍历
void perorder(BinTree bt)
{
if(bt!=NULL)
{
visit(bt);
perorder(bt->lchild);
perorder(bt->rchild);
}
}

2.1.2)中序遍历
void inorder(BinTree bt)
{
if(bt!=NULL)
{
inorder(bt->lchild);
visit(bt);
inorder(bt->rchild);
}
}

2.1.3)后序遍历
void postorder(BinTree bt)
{
if(bt!=NULL)
{
postorder(bt->lchild);
postorder(bt->rchild);
visit(bt);
}
}
2.2)二叉树的层次遍历
思路:利用一个队列,首先将根(头指针)入队列,以后若队列不空则取队头元素p,
如果p不空,则访问之,然后将其左右子树入队列,如此循环直到队列为空。
void Levelorder(BinTree bt)
{
InitQueue(Q) // 队列初始化为空
Enqueue(Q,bt) //根入队列
while(!Emptyqueue(Q)) //队列不空则继续遍历
{
Getqueue(Q,bt); //取队头元素
if(NULL !=p)
{
visit(p->data);
Enqueue(Q,p->lchild) //左右子树入队
Enqueue(Q,p->rchild;
}
}
}

2.3)二叉树遍历的非递归实现

一般借助栈实现。设想一指针沿二叉树 中序遍历顺序移动,每当向上层移动时就要出栈。
中序非递归遍历最最重要,后面的两个用于提高。(a)中序非递归遍历 指针p从根开始,
首先沿着左子树向下移动,同时入栈保存;当到达空子树后需要退栈访问结点,
然后移动到右子树上去。

树和森林
一).树的存储结构
1.孩子表示法

2.孩子兄弟链表表示法

3.双亲表示法

四、图

五、查找

六、排序
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构