按后序运行时,运行不了
```c
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
int data;
struct node* left;
struct node* right;
}Node;
void preorder(Node* node) {
if (node != NULL) {
printf("%d\n", node->data);
preorder(node->left);
preorder(node->right);
}
}
void inorder(Node* node) {
if (node != NULL) {
inorder(node->left);
printf("%d\n", node->data);
inorder(node->right);
}
}
void postorder(Node* node) {
if (node != NULL); {
postorder(node->left);
postorder(node->right);
printf("%d\n", node->data);
}
}
int main() {
Node n1;
Node n2;
Node n3;
Node n4;
n1.data = 5;
n2.data = 6;
n3.data = 7;
n4.data = 8;
n1.left = &n2;
n1.right = &n3;
n2.left = &n4;
n2.right = NULL;
n3.left = NULL;
n3.right = NULL;
n4.left = NULL;
n4.right = NULL;
postorder(&n1);
}
```
if (node != NULL);
->
if (node != NULL)
多了分号
1.线性表动态分配顺序存储结构
#define List_INIT_SIZE 100//线性表存储空间的初始分配量
#define ListINCREMENT 10//线性表存储空间的分配增量
typedef struct{
ElemType *elem;//存储空间基址
int length;//当前长度
int listsize;//当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList
其中,数组指针elem指示线性表的基地址,length指示线性表的当前长度,listsize指示顺序表当前分配的存储空间大小,一旦因为插入元素而空间不足时,可进行再分配,即为顺序表增加一个大小为存储LISTINCREMENT个数据元素的空间。
下面进行顺序表的初始化操作,其实就是为顺序表分配一个预定义大小的数组空间,并将线性表的当前长度设为0。
/*初始化线性表*/
Status InitList_Sq(SqList &L){
//构造一个空的线性表L
L.elem = (ElemType *)malloc(List_INIT_SIZE*sizeof(ElemType));
if (!L.elem) exit(OVERFLOW);//存储空间分配失败
L.length = 0;//空表长度为0
L.listsize = LIST_INT_SIZE;//初始存储容量
return OK
}
下面介绍线性表的插入和删除两种操作在顺序存储表示时的实现方法。
例3:线性表插入操作:
思路:一般情况下,在第i个(1=<i<=n)个元素之前插入一个元素时,需要将第n至第i(共n-i+1个元素向后移动一个位置)
算法如下:
/*在顺序线性表L中第i个位置之前插入新的元素e*/
Status ListInsert_Sq(Sqlist &L,int i,ElemType e){
//i的合法值为1=<i<=L.length+1
if (i<1 || i>L.length+1) return Error;//i值不合法
if (L.length>=L.listsize){//当前存储空间已满,增加分配
newbase = (ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if (!newbase) exit(OVERFLOW);//存储分配失败
L.elem = newbase;//新的基址
L.listsize +=LISTINCREMENT;//增加存储容量
}
q = &(L.elem[i-1]);//q为插入的位置
for(p=&(L.elem[L.Length-1]);p>=q;--p) *(p+1) = *p;//插入的位置以及之后的元素右移
*q = e;//插入e
++L.length;//表长增加1
return OK;
}
例4:线性表删除操作
思路:一般情况下,删除第i个(1<=i<=n)个元素时,需要将从第i+1到第n(共n-i)个元素依次向前移动一个位置。
算法如下:
/*在顺序线性表L中删除第i个元素,并用e返回其值*/
Status ListDelete_Sq(SqList &L,int i,ElemType &e){
//i的合法值为1=<i<=L.length
if((i<1) || (i>L.length)) return Error;//i值不合法
p = &(L.elem[i-1]);//p为被删除元素的位置
e = *p;//被删除元素赋值给e
q = L.elem+L.length-1;//表尾元素的位置
for(++p;p<=q;++p)*(p-1) = *p;//被删除元素之后的元素左移
--L.length;//表长减去1
return OK;
}
通过上面两种操作方式可知,当在顺序存储结构的线性表中某个位置上插入或者删除一个数据元素时,其时间主要耗费在移动元素中,也就是说移动元素的操作为预估算法时间复杂度的基本操作,而移动元素的个数取决于插入和删除元素的位置。在顺序存储结构的线性表中插入或者删除一个数据元素,平均约移动表中一半的元素。若表长为n,则上面两个算法的时间复杂度为O(n)。
在这里我们讨论下例题1和例题2中的操作在顺序存储的线性表中的实现和时间复杂度的分析。容易看出,顺序表的“求表长”“取第i个数据元素”的时间复杂度均为O(1),而且这两个例子中进行的插入操作都在表尾进行,则不需要移动元素。
对于例题1的执行时间主要取决于查找函数LocateElem的执行时间,在顺序表中查找是否存在和e相同的数据元素的最简便的方法是,令e和L中的数据元素依次比较。基本操作是“进行两个元素之间的比较”,若L中存在和e相同的元素ai,则比较次数为i,否则为L.length,算法实现如下:
/*在顺序线性表L中查找第一个值与e满足compare()的元素的位序*/
int LocateElem_Sq(SqList L,ElemType e,Status(*compare)(ElemType,ElemType)){
//若找到,则返回其在L中的位序,否则返回0
i=1;//i的初值为第1个元素的位序
p=L;//p的初值为第一个元素的储存位置
while(i<=L.length&&!(*compare)(*p++,e)) ++i;
if(i<=L.length) return i;
else return 0;
}
上面算法的时间复杂度为O(L.length),因此,对于顺序表La和Lb而言,例题1的时间复杂度为O(La.length*Lb.length)
对于例题2,可直接写出如下算法,时间复杂度为O(La.length+Lb.length),实现顺序表的合并。
/*已知顺序线性表La和Lb的元素按照值非递减排列
归并La和Lb得到新的顺序线性表Lc,Lc的元素也按照值非递减排列
*/
void MergeList_Sq(SqList La,Sqlist Lb,SqList &Lc){
pa = La.elem;pb=Lb.elem;
Lc.listsize = Lc.length=La.length+Lb.length;
pc = Lc.elem=(ElemType*)malloc(Lc.listsize*sizeof(ElemType));
if (!Lc.elem) exit(OVERFLOW);//存储分配失败
pa_last = La.elem+La.length-1;
pb_last = Lb.elem+Lb.length-1;
while(pa<=pa_last&&pb<=pb_last){//合并
if (*pa<=*pb) *pc++=*pa++;
else *pc++=*pb++;
}
while(pa<=pa_last) *pc++=*pa++;//插入La的剩余元素
while(pb<=pb_last) *pc++=*pb++;//插入Lb的剩余元素
}
上面算法的时间复杂度为O(La.length+LB.length)