数据结构的本质:
数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系,并对这种结构定义相应的运算。
什么是逻辑结构?
数据之间的逻辑关系,我们通常分成四种:
1)集合 , 结构中的数据元素除了同属于一种类型外,别无其它关系。
2)线性结构 , 结构中的数据元素之间存在一对一的关系。
3)树型结构 , 结构中的数据元素之间存在一对多的关系。
4)图状结构或网状结构 , 结构中的数据元素之间存在多对多的关系。
什么是物理结构?
数据在内存中的存储形式,我们通常分成两种:
1)顺序存储,在内存中严格连续存放,可以通过数组来实现;
2)链式存储,在内存中不连续存放,可以通过指针来实现。
逻辑结构和物理结构的相互关系有什么意义?
逻辑结构越复杂,顺序存储缺点越明显,链式存储优点越突出。
注:以下均以链式存储来分析。
单向链表
typedef struct node
{
datetype val; //结点的内容
struct node *next; //指向下一个结点
}
双向链表
typedef struct node
{
datetype val; //结点的内容
struct node *head; //指向前一个结点
struct node *rear; //指向后一个结点
}
二叉树
由一个根结点及两棵互不相交的左右子树组成,并且左右子树都是二叉树。
typedef struct btree
{
datetype val; //结点内容
btree *left; //指向左子树
btree *right; //指向右子树
}B;
/*
文件名:Btree.c
摘要:
1)利用递归的思想创建二叉树,先访问根节点,再访问左结点,最后访问右结点(先序遍历的思想——DLR)。
2)利用堆栈输出二叉树,遍历左树——入栈——出栈——遍历右树。
完成日期:2012-7-3 15:23
作者:黄路
*/
#include<stdio.h>
#include<stdlib.h>
typedef struct Bitree
{
int data;
struct Bitree *Lchild; //左子树
struct Bitree *Rchild; //右子树
}BitreeNode;
typedef BitreeNode *LinkBitree;
typedef struct Stack
{
LinkBitree data[20];
int top,bottom;
}Stack;
typedef Stack *StackList;
//建树
LinkBitree CreatBitree();
//初始化栈
StackList InitStack();
//先序输出
void InorderTraverse(LinkBitree Head, StackList Stack);
int main()
{
LinkBitree BitreeHead;
StackList Stack;
printf("请输入根结点的值:e = ");
BitreeHead = CreatBitree();
Stack = InitStack();
InorderTraverse(BitreeHead, Stack);
return 0;
}
/*
功能:利用‘递归的思想’创建 树
输入:键盘输入根节点
输出:树
*/
LinkBitree CreatBitree()
{
int edata;//根结点
LinkBitree Head;
scanf("%d", &edata);
//如果根节点为0,则停止在此根结点上建子树
if(edata==0)
{
Head = NULL;
}
else
{
Head = (LinkBitree)malloc(sizeof(BitreeNode));
//memory check
if(Head == NULL)
{
printf("内存分配失败!!");
exit(0);
}
else
{
Head->data = edata;
printf("请输入结点%d的左孩子的值:e= ", Head->data);
Head->Lchild = CreatBitree();
printf("请输入结点%d的右孩子的值:e= ", Head->data);
Head->Rchild = CreatBitree();
}
}
return Head;
}
/*
功能:初始化栈
栈空间是用来存放 子树的。
*/
StackList InitStack()
{
StackList Stack;
Stack = (StackList)malloc(sizeof(Stack));
if(Stack == NULL)
{
printf("内存分配失败!!");
exit(0);
}
else
{
Stack->top = 0;
Stack->bottom = 0;
}
return Stack;
}
//先访问根结点,再访问左树,再访问右树
void InorderTraverse(LinkBitree Head, StackList Stack)
{
do
{
while (Head != NULL) //穷尽所有的左子树为止
{
printf("%d ", Head->data); //打印左树的根结点
Stack->data[Stack->top] = Head;//将访问过的子树入栈
Stack->top++; //栈头
Head = Head->Lchild; //访问下一个左子树
}
if (Stack->top != 0)//穷尽栈为止
{
Stack->top--;
Head = Stack->data[Stack->top]; //出栈
Head = Head->Rchild; //访问下一个右子树
}
}
while(Stack->top != 0 || Head != NULL);
}