南昌航空大學實驗報告
二0 21 年 5 月 27 日
課程名稱: 數據結構實驗 實驗名稱: 線性表的鏈式存儲結構
班級: 姓名: 同組人:
指導教師評定: 簽名:
必做1:
一、 需求分析
題目:設計並驗證如下算法:按后序序列建立二叉樹的二叉鏈表結構,求其單分支結點數目,雙分支結點數目,並交換該二叉樹。
1、在本次實驗中,首先,從鍵盤輸入,按照輸入字符構建二叉樹,在進行二叉樹交換與先序遞歸遍歷並輸出,輸出單分支結點數目與雙分支結點數目。
2. 演示程序以用戶和計算機對話的方式進行,即在計算機終端上顯示“提示信息”之后,按照提示信息輸入。
3. 程序執行的命令包括:
(1) 輸入二叉樹信息;
(2) 后序遞歸構建二叉樹
(3) 交換二叉樹
(4) 交換前先序遞歸遍歷
(5) 交換后先序遞歸遍歷
4. 測試數據
請輸入:
##b##d#ca
單分支節點數目:1,雙分支節點數目:1
先序遍歷:
a b c d
交換后先序遍歷為:
a c d b
二、 概要設計
1. 抽象數據類型定義
為實現上述程序功能,需要一個抽象數據類型:圖。
ADT Graph{
基本操作:
InitBiTree(BiTree *BT)
操作結果:二叉樹初始化
CreateBiTree(BiTree *BT,char ch[],int &count1,int &count2,int &count3)
操作結果:后序遞歸建立二叉樹
Exchange(BiTree *BT)
操作結果:交換二叉樹
PreOrder(BiTree BT)
操作結果:先序遍歷二叉樹
2.程序模塊
(1)主程序流程
void main{
初始化兩個二叉樹;
輸入;
后序遍歷創建二叉樹;
輸出單分支,雙分支結點數目;
先序遍歷二叉樹;
交換二叉樹;
先序遍歷交換后的二叉樹;
}
(2)二叉樹初始化;
(3)后序遍歷建二叉樹;
(4)交換二叉樹;
(5)先序遍歷二叉樹;
3.程序結構圖
各模塊之間的調用關系如圖所示。
圖1 模塊之間調用關系圖
三、 詳細設計
1.數據類型及結構體
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;
typedef BiTree QElemType;
Status InitBiTree(BiTree *BT){/*構造空二叉樹*/
Status CreateBiTree(BiTree *BT,char ch[],int &count1,int &count2,int &count3){/*后序遞歸建立二叉樹*/
Status Exchange(BiTree *BT){/*交換二叉樹*/
Status PreOrder(BiTree BT){/*先序遞歸遍歷*/
- 主函數
int main(){
BiTree BT,BT1;
InitBiTree(&BT);
InitBiTree(&BT1);
int count1=0,count2=0,count3=0;
printf("請輸入:\n");
TElemType ch1[100],ch2[100];
scanf("%s",&ch1);
int i=0;
int k=strlen(ch1);
for(int j=0,i=k-1;j<k;j++,i--)
{
ch2[j]=ch1[i];
}
CreateBiTree(&BT,ch2,count1,count2,count3);/*創建二叉樹,返回根節點BT*/
printf("單分支結點數目:%d,雙分支結點數目:%d\n",count2,count1);
printf("先序遍歷為:\n");
PreOrder(BT);
printf("\n");
Exchange(&BT);
printf("交換后先序遍歷為:\n");
PreOrder(BT);
return 0;
}
四、 調試分析
1. 第一次為了得到單分支與雙分支結點數目采用了全局變量,改正后采用傳地址來達到記錄數據的目的:CreateBiTree(&BT,ch2,count1,count2,count3)。
2.后序遍歷建樹最開始沒思路,后來將輸入字符串顛倒借助先序遍歷建數(先序建樹時先建右孩子在建左孩子)來實現。
3.整體代碼的時間復雜度為O(n),每種操作對於每個結點而言都只遍歷了一次,
五、 用戶手冊
1. 本程序的運行環境為DOS操作系統,執行文件為:main.exe。
2. 進入演示程序后即顯示文本方式的用戶界面。
3. 程序運行后,按照提示信息輸入后序遍歷二叉樹的結果
4. 建樹后輸出先序遍歷的結果,單分支雙分支結點數目,先序遍歷交換左右孩子后樹的結果。
六、 測試結果
測試結果
請輸入:
##b##d#ca
單分支節點數目:1,雙分支節點數目:1
先序遍歷:
a b c d
交換后先序遍歷為:
a c d b
七、 附錄
源代碼:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;
typedef BiTree QElemType;
Status InitBiTree(BiTree *BT){/*構造空二叉樹*/
*BT=NULL;
}
Status CreateBiTree(BiTree *BT,char ch[],int &count1,int &count2,int &count3){/*后序遞歸建立二叉樹*/
if(ch[count3]=='#'){
*BT=NULL;
count3++;
}
else{
*BT=(BiTree)malloc(sizeof(BiTree));
int k=ch[count3];
count3++;
CreateBiTree(&((*BT)->rchild),ch,count1,count2,count3);
CreateBiTree(&((*BT)->lchild),ch,count1,count2,count3);
(*BT)->data = k;
if((*BT)->lchild!=NULL&&(*BT)->rchild!=NULL)
count1++;
if(((*BT)->lchild!=NULL&&(*BT)->rchild==NULL)||((*BT)->lchild==NULL&&(*BT)->rchild!=NULL))
count2++;
}
}
Status Exchange(BiTree *BT){/*交換二叉樹*/
if(*BT){
BiTree p;
p = (*BT)->lchild;
(*BT)->lchild = (*BT)->rchild;
(*BT)->rchild = p;
Exchange(&(*BT)->lchild);
Exchange(&(*BT)->rchild);
}
}
Status PreOrder(BiTree BT){/*先序遞歸遍歷*/
if(BT){
if(!(BT->data))
return ERROR;
printf("%c ",BT->data);
PreOrder(BT->lchild);
PreOrder(BT->rchild);
return OK;
}
}
int main(){
BiTree BT,BT1;
InitBiTree(&BT);
InitBiTree(&BT1);
int count1=0,count2=0,count3=0;
printf("請輸入:\n");
TElemType ch1[100],ch2[100];
scanf("%s",&ch1);
int i=0;
int k=strlen(ch1);
for(int j=0,i=k-1;j<k;j++,i--)
{
ch2[j]=ch1[i];
}
CreateBiTree(&BT,ch2,count1,count2,count3);/*創建二叉樹,返回根節點BT*/
printf("單分支結點數目:%d,雙分支結點數目:%d\n",count2,count1);
printf("先序遍歷為:\n");
PreOrder(BT);
printf("\n");
Exchange(&BT);
printf("交換后先序遍歷為:\n");
PreOrder(BT);
return 0;
}
必做2:
一、 需求分析
題目:設計並驗證如下算法:輸入一棵二叉樹的廣義表形式,建立該二叉樹的二叉鏈表結構,並求其總結點數目。
1、在本次實驗中,首先,從鍵盤輸入二叉樹廣義表形式,按照輸入字符構建二叉樹,輸出二叉樹的先序遍歷以及總結點數目。
2. 演示程序以用戶和計算機對話的方式進行,即在計算機終端上顯示“提示信息”之后,按照提示信息輸入。
3. 程序執行的命令包括:
(1) 輸入二叉樹信息;
(2) 構建二叉樹;
(3) 輸出總結點數目;
(4) 先序遍歷二叉樹
4. 測試數據
請輸入:
C(E,(I,J),F(,G(K,H))#
總結點數目為:8
輸出先序遍歷:
C E I J F G K H
二、 概要設計
1. 抽象數據類型定義
為實現上述程序功能,需要一個抽象數據類型:圖。
ADT Graph{
基本操作:
PreOrder(BiTree BT)
操作結果:輸出先序遞歸遍歷二叉樹
CreatTree(BiTree & BT)
操作結果:建立二叉樹
2.程序模塊
(1)主程序流程
void main{
初始化二叉樹;
創建二叉樹;
先序遍歷二叉樹;
}
(2)二叉樹初始化;
(3)建二叉樹;
(4)先序遍歷二叉樹
3.程序結構圖
各模塊之間的調用關系如圖所示。
圖1 模塊之間調用關系圖
三、 詳細設計
1.數據類型及結構體
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
Status PreOrder(BiTree BT)/*先序遞歸遍歷*/
Status CreatTree(BiTree & BT);/*建立二叉樹*/
2.主函數
int main(){
BiTree BT;
printf("請輸入:\n");
CreatTree(BT);
printf("輸出先序序列:\n");
PreOrder(BT);
return 0;
}
四、 調試分析
1. 第一次建樹用了for循環發現很混亂,便改用switch語句,使得代碼更加清楚簡潔
2.第一次入隊列出隊列的條件沒搞清楚,什么時候該不該進隊列,改進后:switch(a[i])
{
case '(':
rear++;
A[rear] = p;
flag = 1;
break;
case ')':
rear--;
break;
case ',':
flag = 0;
break;
default:
p = (BiTNode *)malloc(sizeof(BiTNode));
p->data = a[i];
p->lchild = p->rchild = NULL;
if(BT==NULL)
BT=p;
else
{
if ( flag == 1)
A[rear]->lchild = p;
else
A[rear]->rchild = p;
}
}
3.整體代碼的時間復雜度為O(n),每種操作對於每個結點而言都只遍歷了一次,
五、 用戶手冊
1. 本程序的運行環境為DOS操作系統,執行文件為:main.exe。
2. 進入演示程序后即顯示文本方式的用戶界面。
3. 程序運行后,按照提示信息輸入二叉樹的順序表形式
4. 建樹后輸出先序遍歷的結果,輸出總結點數目。
六、 測試結果
測試結果
請輸入:
C(E,(I,J),F(,G(K,H))#
總結點數目為:8
輸出先序遍歷:
C E I J F G K H
七、 附錄
源代碼:
#include<stdio.h>
#include<stdlib.h>
#define STACK_SIZE 100
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
Status PreOrder(BiTree BT){/*先序遞歸遍歷*/
if(BT){
printf("%c ",BT->data);
PreOrder(BT->lchild);
PreOrder(BT->rchild);
}
}
Status CreatTree(BiTree & BT){
TElemType a[STACK_SIZE];
scanf("%s",a);
BiTree p;
BiTree A[100];
int rear = -1;
BT=NULL;
int flag=0;//1指左,0指右
int i=0,j=0;
while(a[i]!='#')
{
if(a[i]!=','&&a[i]!='('&&a[i]!=')')
j++;
switch(a[i])
{
case '(':
rear++;
A[rear] = p;
flag = 1;
break;
case ')':
rear--;
break;
case ',':
flag = 0;
break;
default:
p = (BiTNode *)malloc(sizeof(BiTNode));
p->data = a[i];
p->lchild = p->rchild = NULL;
if(BT==NULL)
BT=p;
else
{
if ( flag == 1)
A[rear]->lchild = p;
else
A[rear]->rchild = p;
}
}
i++;
}
printf("總結點數目為:%d\n",j);
}
int main(){
BiTree BT;
printf("請輸入:\n");
CreatTree(BT);
printf("輸出先序序列:\n");
PreOrder(BT);
return 0;
}