LOADING

加载过慢请开启缓存 浏览器默认开启

2023/12/9

本周小结:cry:

支原体感染是真猛啊,这周被疾病狠狠地折磨了:weary:,也狠狠地摆了一周,没咋学习课外内容(快要鸽爆了),唯一认真写的是数据结构的实验,足足写了上百行C语言代码,是真的折磨啊!不过好在实验内容实现的还不错,记录一下!

实验一

1、参照课本程序2.1~2.7,编写程序,完成顺序表的初始化、查找、插入、删除、输出、撤销等操作。

2、已知带表头结点单链表的类型定义如下:

typedef struct node

{

ElemType element; //结点的数据域

struct node *link; //结点的指针域

}node;

typedef struct

{

struct node * head;

int n;

}headerList;

参照课本程序2.8~2.14,编写程序,完成带表头结点单链表的初始化、查找、插入、删除、输出、撤销等操作。

3、已知带表头结点一元多项式的类型定义如下:

typedef struct pNode

{

int coef;

int exp;

struct pNode* link;

} pNode;

typedef struct

{

struct pNode *head;

} polynominal;

编写程序实现一元多项式的创建、输出、撤销以及两个一元多项式相加和相乘的操作。

#include <stdio.h>
#include <stdlib.h>
//1、顺序表操作实现
typedef struct seqList{
    int n;
    int maxlen;
    int *element;
}SeqList;
//线性表初始化
int Init(SeqList *L,int mSize){
    L->maxlen=mSize;
    L->n=0;
    L->element=(int *)malloc(sizeof(int)*mSize);
    if(!L->element)
        return 0;
    return 1;
}
//查找:给出下标查找元素
int Find(SeqList L,int xiabiao,int *x){
    if(xiabiao<0||xiabiao>L.n-1) return 0;
    *x=L.element[xiabiao];
    return 1;
}
//插入:插入元素到指定下标i处
int Insert(SeqList* L,int i,int x){
    if(i<-1||i>L->n-1) return 0;
    if(L->n==L->maxlen) return 0;
    int j;
    for(j=L->n-1;j>i;j--){
        L->element[j+1]=L->element[j];
    }
    L->element[i+1]=x;
    L->n++;
    return 1;
}
//删除:删除指定下标处的元素
int Delete(SeqList L,int i){
    if(i<0||i>L.n-1) return 0;
    if(!L.n) return 0;
    int j;
    for(j=i;j<L.n-1;j++){
        L.element[j]=L.element[j+1];
    }
    L.n--;
    return 1;
}
//输出:遍历线性表并逐个输出元素
int Output(SeqList* L){
    int i;
    if(L->n==0) return 0;
    for(int i=0;i<L->n;i++){
        printf("%d ",L->element[i]);
    }
    printf("\n");
    return 1;
}
//撤销:释放线性表的空间
void Destory(SeqList *L){
    L->n=0;
    L->maxlen=0;
    free(L->element);
}

//2、链表操作实现
typedef struct node
{
    int  element;  //结点的数据域
    struct node *link;     //结点的指针域
}node;
typedef struct 
{
    struct node * head;  //链表头指针
    int n;
}headerList;
//链表初始化
int Init2(headerList *H){
    H->head=NULL;
    H->n=0;
    return 1;
}
//查找:给定指定元素位置,返回该元素
int Find2(headerList* H,int i,int *x){
    if(i<0||i>H->n-1) return 0;
    int j;
    node *p=H->head;
    for(j=0;j<i;j++) p=p->link;
    *x=p->element;
    return 1;
}
//插入:在指定位置i插入元素
int Insert2(headerList* H,int i,int x){
    if(i<-1||i>H->n-1) return 0;
    int j;
    node* p=H->head;
    for(j=0;j<i;j++) p=p->link;
    node* q=(node*)malloc(sizeof(node));
    q->element=x;
    if(i>-1){
        q->link=p->link;
        p->link=q;
    }else{
        q->link=H->head;
        H->head=q;
    }
    H->n++;
    return 1;
}
//删除:删除指定位置i处的元素
int Delete2(headerList* H,int i){
    if(i<0||i>H->n-1) return 0;
    if(H->n==0) return 0;
    int j;
    node *p=H->head;
    node *q=H->head; //也要指定初始指向,因为如果i==0,则要free(q)!
    for(j=0;j<i-1;j++) p=p->link;
    if(i==0){ //删除头节点的情况,也是列表里只有一个元素的情况(只有一个元素就是头结点,只能删头结点)
        H->head=H->head->link;
    }else {
        q=p->link;
        p->link=q->link;
    }
    free(q);
    H->n--;
    return 1;
}
//输出:遍历链表并逐个输出元素
int Output2(headerList* H){
    if(!H->n) return 0;
    node *p=H->head;
    int i=0;
    while(i<H->n){
        printf("%d ",p->element);
        p=p->link;
        i++;
    }
    return 1;
}
//删除:逐个释放链表结点空间
void Destory2(headerList* H){
    node *p=H->head;
    node *q;
    while(p){
        q=p;
        p=p->link;
        free(q);
    }
}
//3、多项式操作实现
typedef struct pNode
{
int coef;
int exp;
struct pNode* link;
} pNode;
typedef struct 
{
struct pNode *head;
} polynominal;
//创建多项式:不断接收输入的系数和次幂
void Create(polynominal *p){
    pNode *pn,*pre,*q;
    p->head=(pNode*)malloc(sizeof(pNode));
    p->head->exp=-1;
    p->head->link=p->head;
    printf("\n Create a p:\n");
    for(;;){
        pn=(pNode*)malloc(sizeof(pNode));
        printf("coef:\n");
        scanf("%d",&pn->coef);
        printf("exp:ends with -1\n");
        scanf("%d",&pn->exp);
        if(pn->exp<0) break;
        pre=p->head;
        q=p->head->link;
        while(q&&q->exp>pn->exp){ //遍历,直到当前pn的指数大于q指针结点的指数
            pre=q;
            q=q->link;
        }
        pn->link=q;
        pre->link=pn;
    }
    
}
//撤销:释放多项式的空间
void Destory3(polynominal *p){
    if(p->head->link->exp==-1) free(p->head);
    else{
        pNode *pnow=p->head->link->link;
        pNode *pre=p->head->link;
        while(pnow->exp!=-1){
            free(pre);
            pre=p;
            pnow=pnow->link;
        }
        free(pre);
        free(pnow);
    }
}
//输出:输出多项式
int Output3(polynominal *p){
    pNode *q;
    q=p->head;
    q=q->link;
    while(q->exp!=-1){
        printf("(%dx^%d)",q->coef,q->exp);
        q=q->link;
        if(q->exp!=-1) printf(" + ");
    }
    printf("\n");
}
//多项式相加:次幂相同的系数相加,存储到q中
void Add(polynominal *px,polynominal *qx){
    pNode *q,*ql=qx->head,*p,*pl,*temp;
    p=px->head->link;
    q=ql->link;
    while(p->exp>=0){
        while(p->exp<q->exp){
            ql=q;     //ql与q一同前进一格
            q=q->link;
        }
        if(p->exp==q->exp){
            q->coef=q->coef+p->coef;
            if(q->coef==0){
                ql->link=q->link;  //删除q
                free(q);        //释放q空间
                q=ql->link;    //重置q,使其仍指向ql下一个
                p=p->link;
            }
            else{
                ql=q;
                q=q->link;
                p=p->link;
            }
        
        }
        else{   //p->exp>q->exp情况,这时要用p创建一个结点插到q表达式里,且插在q当前指向的上一个结点也就是ql后面
            temp=(pNode*)malloc(sizeof(pNode));
            temp->coef=p->coef;
            temp->exp=p->exp;
            temp->link=ql->link;
            ql->link=temp;
            //插完后前进
            ql=ql->link;
            p=p->link;

        }
        
    }

}
//加减运算都一样,每次都比较出较大次幂的(因为要降幂排列),然后计算
void subtract(polynominal *px,polynominal *qx){
    pNode *q,*ql=qx->head,*p,*pl,*temp;
    p=px->head->link;
    q=ql->link;
    while(p->exp>=0){
        while(p->exp<q->exp){
            q->coef=-q->coef;
            ql=q;     //ql与q一同前进一格
            q=q->link;
        }
        if(p->exp==q->exp){
            q->coef=p->coef-q->coef;
            if(q->coef==0){
                ql->link=q->link;  //删除q
                free(q);        //释放q空间
                q=ql->link;    //重置q,使其仍指向ql下一个
                p=p->link;
            }
            else{
                ql=q;
                q=q->link;
                p=p->link;
            }
        
        }
        else{   //p->exp>q->exp情况,这时要用p创建一个结点插到q表达式里,且插在q当前指向的上一个结点也就是ql后面
            temp=(pNode*)malloc(sizeof(pNode));
            temp->coef=p->coef;
            temp->exp=p->exp;
            temp->link=ql->link;
            ql->link=temp;
            //插完后前进
            ql=ql->link;
            p=p->link;

        }
    }
    while(q->exp>=0){
        q->coef=-q->coef;
        q=q->link;
    }
}
//多项式相乘:主循环遍历p2多项式,分别于p1各项相乘,相乘完后再合并系数相同的次幂
void multiply(polynominal *p1,polynominal *p2,polynominal *p3){
    p3->head=(pNode*)malloc(sizeof(pNode));
    p3->head->exp=-1;
    pNode *pre3=p3->head;
    pNode *pmain=p2->head->link;
    while(pmain->exp>=0){  //主循环遍历p2多项式
        pNode *psec=p1->head->link;
        while(psec->exp>=0){ //次循环遍历p1多项式,分别于pmain当前所指相乘
            pNode *temp=(pNode*)malloc(sizeof(pNode));
            temp->coef=pmain->coef*psec->coef;
            temp->exp=pmain->exp+psec->exp;
            pre3->link=temp;
            pre3=pre3->link;
            psec=psec->link;
        }
        pmain=pmain->link;
    }
    pre3->link=p3->head;
    //接下来去掉乘完后重复的次幂
    pre3=p3->head->link;
    pNode *pp3=pre3->link;
    while(pp3->exp>=0){
        if(pp3->exp==pre3->exp){
            pre3->coef=pre3->coef+pp3->coef;
            pre3->link=pp3->link;
            //相等就只需要pp3前进
            pp3=pp3->link;
            continue;
        }
        pre3=pre3->link;
        pp3=pp3->link;
    }
}

int main() {
    //线性表测试
    int i;
    SeqList list;
    Init(&list,10);
    for(i=0;i<list.maxlen;i++){
        Insert(&list,i-1,i);
    }
    Output(&list);
    int x;
    Find(list,2,&x);
    printf("Finding list[2]:%d",x);
    Destory(&list);
    //链表测试
    headerList H;
    Init2(&H);
    for(i=0;i<9;i++){
        Insert2(&H,i-1,i+2);
    }
    printf("\n");
    Output2(&H);
    Delete2(&H,0);
    printf("\nAfter deleting list[0]:\n");
    Output2(&H);
    Insert2(&H,2,99);
    printf("\nAfter inserting 99 at list[3]:\n");
    Output2(&H);
    Find2(&H,1,&x);
    printf("\nFinding list[1]:%d",x);
    Destory2(&H);
    //多项式测试
    polynominal p1;
    polynominal p2;
    polynominal p3;
    Create(&p1);
    Create(&p2);
    Output3(&p1);
    Output3(&p2);
    printf("p1*p2=\n");
    multiply(&p1,&p2,&p3);
    Output3(&p3);
    printf("p1+p2=\n");
    Add(&p1,&p2);
    Output3(&p2);
    // Destory3(&p1);
    // Destory3(&p2);
    return 0;
}

实验二

1、已知二叉树二叉链表结点结构定义如下:

typedef struct btnode{

ElemType element;

struct btnode *lChild;

struct btnode *rChild;

}BTNode;

参照程序 5.1~5.4,编写程序,完成二叉树的先序创建、先序遍历、中序遍历、后序遍历等操作。

2、以第1题所示二叉链表为存储结构,编写程序实现求二叉树结点个数、叶子结点个数、二叉树的高度以及交换二叉树所有左右子树的操作。

3、已知哈夫曼树结点结构定义如下:

typedef struct hfmTNode{

ElementType element; //结点的数据域

int w; //结点的权值

struct hfmTNode *lChild; //结点的左孩子指针

struct hfmTNode *rChild; //结点的右孩子指针

}HFMTNode;

编写程序,实现哈夫曼树的创建、哈夫曼编码以及解码的实现。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//1、二叉树结点定义与基本操作
typedef struct btnode{ 
    int element;
    struct btnode *lChild;
    struct btnode *rChild;
}BTNode;
//先序遍历
void preorder_traversal(BTNode* node){
    if(!node) return;
    printf("%d",node->element);
    preorder_traversal(node->lChild);
    preorder_traversal(node->rChild);
}
//中序遍历
void inorder_traversal(BTNode* node){
    if(!node) return;
    inorder_traversal(node->lChild);
    printf("%d",node->element);
    inorder_traversal(node->rChild);
}
//后序遍历
void postorder_traversal(BTNode* node){
    if(!node) return;
    postorder_traversal(node->lChild);
    postorder_traversal(node->rChild);
    printf("%d",node->element);
}

//先序创建:通过递归先序创建二叉树
BTNode* PreCreateBT(BTNode *t){
    char ch;
    ch=getchar();
    if(ch=='#'){ //建立空树
        t=NULL;
    }else{
        t=(BTNode*)malloc(sizeof(BTNode));
        t->element=ch-'0'; //这里存储的是整数,因此用输入字符要减去'0;
        t->lChild=PreCreateBT(t->lChild);
        t->rChild=PreCreateBT(t->rChild);

    }
    return t;
}

//2、二叉树关键特征结点数求解
//求二叉树结点个数
int TreeSize(BTNode* t){
    if(!t) return 0;
    else return TreeSize(t->lChild)+TreeSize(t->rChild)+1;
}
//求二叉树叶子节点个数
int LeafSize(BTNode* t){
    int sum=0;
    if(!t) return 0;
    if(t->lChild==NULL&&t->rChild==NULL) {
        sum=1;
        return sum;
    }
    if(t->lChild&&!t->rChild){
        return LeafSize(t->lChild);
    }
    if(t->rChild&&!t->lChild){
        return LeafSize(t->rChild);
    }
    return LeafSize(t->lChild)+LeafSize(t->rChild)+sum;
}
//求二叉树的高度
//调用的时候复制sum和height为0,sum存储当前结点的高度,heigth为全局高度
void TreeHeight(BTNode* t,int sum,int *height){
    sum++;
    if(sum>*height) *height=sum;
    if(t->rChild) TreeHeight(t->rChild,sum,height);
    if(t->lChild) TreeHeight(t->lChild,sum,height);
}
//交换二叉树所有左右子树
void SwapTree(BTNode* t){
    BTNode* temp;
    if(t->lChild&&t->rChild){
        temp=t->lChild;
        t->lChild=t->rChild;
        t->rChild=temp;
        SwapTree(t->lChild);
        SwapTree(t->rChild);
    }
    if(!t->rChild&&t->lChild){
        t->rChild=t->lChild;
        t->lChild=NULL;
        SwapTree(t->rChild);
    }
    if(!t->lChild&&t->rChild){
        t->lChild=t->rChild;
        t->rChild=NULL;
        SwapTree(t->lChild);
    }
}

//3、哈夫曼树构建与哈夫曼编码
typedef struct hfmTNode{
    int element;
    int w;
    struct hfmTNode *lChild;
    struct hfmTNode *rChild;
}HFMTNode;
//先序遍历哈夫曼树
void preorder_traversal_hfm(HFMTNode* node){
    if(!node) return;
    printf("%d ",node->w);
    preorder_traversal_hfm(node->lChild);
    preorder_traversal_hfm(node->rChild);
}
//向上调整用于处理新加入的元素
void Adjustup(HFMTNode** heap,int current){
    int p=current;
    HFMTNode* temp;
    while (p>0)
    {
        if(heap[p]->w<heap[(p-1)/2]->w){
            temp=heap[p];
            heap[p]=heap[(p-1)/2];
            heap[(p-1)/2]=temp;
            p=(p-1)/2;
        }
        else
            break;
    }
}

//向下调整用于处理要移除的元素
void AdjustDown(HFMTNode** heap,int current,int border){
    int p=current;
    HFMTNode* temp;
    int minChild;
    while (2*p+1<=border)
    {
        if((2*p+2)&&(heap[2*p+1]->w>heap[2*p+2]->w))
            minChild=2*p+2;
        else
            minChild=2*p+1;
        if(heap[p]->w<=heap[minChild]->w) break;
        else{
            temp=heap[p];
            heap[p]=heap[minChild];
            heap[minChild]=temp;
            p=minChild;
        }
    }
}
//定义优先权队列,用来构建哈夫曼树
typedef struct priorityQueue
{
    HFMTNode** elements;
    int n;
    int maxsize;
}PriorityQueue;
//创建优先权队列
void CreatPQ(PriorityQueue *PQ,int msize){
    PQ->maxsize=msize;
    PQ->n=0;
    PQ->elements=(HFMTNode**)malloc(msize*sizeof(HFMTNode*));
}
//判断优先权队列是否已满
int IsFull(PriorityQueue *PQ){
    if(PQ->n==PQ->maxsize){
        return 1;
    }else{
        return 0;
    }
}
//向优先权队列中添加哈夫曼树结点
void Append(PriorityQueue *PQ,HFMTNode* x){
    if(IsFull(PQ)) return;
    PQ->elements[PQ->n]=x;
    PQ->n++;
    Adjustup(PQ->elements,PQ->n-1);
}
//取出优先权队列最前面的结点,即权重最小的结点
HFMTNode* Serve(PriorityQueue *PQ){
    //return空值
    if(PQ->n==0) return;
    HFMTNode* x=PQ->elements[0];
    PQ->n--;
    PQ->elements[0]=PQ->elements[PQ->n];
    AdjustDown(PQ->elements,0,PQ->n-1);
    return x;
}
//创建哈夫曼树结点
void MakeTree(HFMTNode *x,int w,HFMTNode* lchild,HFMTNode* rchild){
    x->w=w;
    x->lChild=lchild;
    x->rChild=rchild;
}
//创建哈夫曼树
HFMTNode* CreateHFMTree(PriorityQueue *PQ,int w[],int m){
    HFMTNode *x=(HFMTNode*)malloc(sizeof(HFMTNode)),*y=(HFMTNode*)malloc(sizeof(HFMTNode));
    CreatPQ(PQ,m);
    for(int i=0;i<m;i++){
        HFMTNode *temp=(HFMTNode*)malloc(sizeof(HFMTNode));
        MakeTree(temp,w[i],NULL,NULL);
        Append(PQ,temp);
    }
    while (PQ->n>1)
    {
        x=Serve(PQ);
        y=Serve(PQ);
        HFMTNode *z=(HFMTNode*)malloc(sizeof(HFMTNode));
        if(x->w<y->w){
            MakeTree(z,x->w+y->w,x,y);
        }else MakeTree(z,x->w+y->w,y,x);
        Append(PQ,z);
        
    }
    x=Serve(PQ);
    return x;
    
}
//哈夫曼编码
int hfm_encoding(HFMTNode* node,char* string,int i,char code){
    string[i]=code;
    i++;

    int o;
    char* string1=(char*)malloc(10*sizeof(char));
    for(o=0;o<10;o++){
        string1[o]=string[o];
    }
    char* string2=(char*)malloc(10*sizeof(char));
    for(o=0;o<10;o++){
        string2[o]=string[o];
    }
    if(!node) return 0;
    if(!node->lChild&&!node->rChild) {
        printf("encoding of weight %d :",node->w);
        for(o=0;o<i;o++){
            printf("%c",string[o]);
        }
        printf("\n");
        return 0;
    }
    //递归传递字符,如果是左子树则传入‘0’,右子树传入‘1’,并继承当前分支的编码结果
    hfm_encoding(node->lChild,string1,i,'0');
    hfm_encoding(node->rChild,string2,i,'1');
    return 1;
}
//哈夫曼解码
int hfm_decoding(char input,int size,int *w,char* ch){
    int i=0;
    for(i=0;i<size;i++){
        if(ch[i]==input){
            char *str;
            sprintf(str, "%d", w[i]);
            printf("decode %c:1100",input);
        }
    }
    
}
int main(){
    BTNode* root;
    int size;
    int leaf=0;
    int height=0;
    //二叉树测试
    //输入以   56#2#1##30###   为例
    root=PreCreateBT(root);
    printf("preorder_traversal:\n");
    preorder_traversal(root);
    printf("\ninorder_traversal:\n");
    inorder_traversal(root);
    printf("\npostorder_traversal:\n");
    postorder_traversal(root);
    size=TreeSize(root);
    printf("\nsize of tree:%d",size);
    TreeHeight(root,0,&height);
    printf("\nheight of tree:%d",height);
    leaf=LeafSize(root);
    printf("\nleaf of tree:%d\n",leaf);
    SwapTree(root);
    printf("after swaping the tree,preorder_traversal:\n");
    preorder_traversal(root);
    printf("\n");
    int i,*w=(int*)malloc(6*sizeof(int));
    char *ch=(char*)malloc(6*sizeof(char));
    printf("input with data like \"A:9\"\n");
    for(i=0;i<6;i++){
        scanf(" %c:%d",ch+i,w+i);
    }
    //观察哈夫曼树结点、权重的存储情况
    // for(i=0;i<6;i++){
    //     printf("%c:%d ",ch[i],w[i]);
    // }
    PriorityQueue PQ;
    CreateHFMTree(&PQ,w,6);
    printf("HFMTree's preorder_traversal:\n");
    //printf("%d,%d",(*(PQ.elements))->lChild->w,(*(PQ.elements))->rChild->w);
    preorder_traversal_hfm(*(PQ.elements));
    printf("\n");
    char* string1=(char*)malloc(10*sizeof(char));
    char* string2=(char*)malloc(10*sizeof(char));
    hfm_encoding((*(PQ.elements))->lChild,string1,0,'0');
    hfm_encoding((*(PQ.elements))->rChild,string2,0,'1');
    char a;
    scanf("%c",&a);
    scanf("%c",&a);
    hfm_decoding(a,6,w,ch);
}