数据结构头歌实验全部代码题

数据结构头歌实验

数据结构与算法 - 线性表

第2关 线性表的顺序表示和实现

/*************************************************************
    date: April 2017
    copyright: Zhu En
    DO NOT distribute this code without my permission.
**************************************************************/
// 顺序表操作实现文件
//
#include <stdio.h>
#include <stdlib.h>
#include "Seqlist.h"

SeqList* SL_Create(int maxlen)
// 创建一个顺序表。
// 与SqLst_Free()配对。
{
	SeqList* slist=(SeqList*)malloc(sizeof(SeqList));
	slist->data = (T*)malloc(sizeof(T)*maxlen);
	slist->max=maxlen;
	slist->len=0;
	return slist;
}

void SL_Free(SeqList* slist)
// 释放/删除 顺序表。
// 与SqLst_Create()配对。
{
	free(slist->data);
	free(slist);
}

void SL_MakeEmpty(SeqList* slist)
// 置为空表。
{
	slist->len=0;
}

int SL_Length(SeqList* slist)
// 获取长度。
{
	return slist->len;
}

bool SL_IsEmpty(SeqList* slist)
// 判断顺序表是否空。
{
	return 0==slist->len;
}

bool SL_IsFull(SeqList* slist)
// 判断顺序表是否满。
{
	return slist->len==slist->max;
}

T SL_GetAt(SeqList* slist, int i)
// 获取顺序表slist的第i号结点数据。
// 返回第i号结点的值。
{
	if(i<0||i>=slist->len) {
		printf("SL_GetAt(): location error when reading elements of the slist!\n");		
		SL_Free(slist);
		exit(0);
	}
	else 
		return slist->data[i];
}

void SL_SetAt(SeqList* slist, int i, T x)
// 设置第i号结点的值(对第i号结点的数据进行写)。
{
	if(i<0||i>=slist->len) {
		printf("SL_SetAt(): location error when setting elements of the slist!\n");		
		SL_Free(slist);
		exit(0);
	}
	else 
		slist->data[i]=x;
}

bool SL_InsAt(SeqList* slist, int i, T x)
// 在顺序表的位置i插入结点x, 插入d[i]之前。
// i 的有效范围[0,plist->len]。
{
    // 请在下面的Begin-End之间补充代码,插入结点。
    /********** Begin *********/
    if(slist->len==slist->max){
        return false;
    }
    for(int j=slist->len;j>i;j--){
        slist->data[j]=slist->data[j-1];
    }
    slist->data[i]=x;
    slist->len++;
    return true;

    /********** End **********/
}

T SL_DelAt(SeqList* slist, int i)
// 删除顺序表plist的第i号结点。
// i的有效范围应在[0,plist->len)内,否则会产生异常或错误。
// 返回被删除的数据元素的值。
{
    // 在下面的Begin-End之间补充代码,删除第i号结点。
    /********** Begin *********/
    if((i<0)||(i>=slist->len)){
        return -1;
    }

    T e = slist->data[i];
    for(int j=i+1;j<slist->len;j++){
        slist->data[j-1]=slist->data[j];
    }
    slist->len--;
    return e;

    /********** End **********/
}

int SL_FindValue(SeqList* slist, T x)
// 在顺序表表中查找第一个值为x的结点,返回结点的编号。
// 返回值大于等于0时表示找到值为x的结点的编号,-1表示没有找到。
{
	int i=0;
	while(i<slist->len && slist->data[i]!=x) i++;
	if (i<slist->len) return i;
	else return -1;
}

int SL_DelValue(SeqList* slist, T x)
// 删除第一个值为x的结点。
// 存在值为x的结点则返回结点编号, 未找到返回-1。
{
    // 在下面的Begin-End之间补充代码,删除第一个值为 x 的结点。
    /********** Begin *********/
    for(int i=0;i<slist->len;i++){
        if(slist->data[i]==x){
            for(int j=i+1;j<slist->len;j++){
                slist->data[j-1]=slist->data[j];
            }
            slist->len--;
            return i; 
        }
    }
    return -1;

    /********** End **********/
}

void SL_Print(SeqList* slist)
// 打印整个顺序表。
{
	if (slist->len==0) {
		printf("The slist is empty.\n");		
		return;
	}

	//printf("The slist contains: ");
	for (int i=0; i<slist->len; i++) {
		printf("%d  ", slist->data[i]);
	}

	printf("\n");	
	
}

第3关 线性表的链式表示和实现

/*************************************************************
    date: April 2017
    copyright: Zhu En
    DO NOT distribute this code without my permission.
**************************************************************/
// 单链表实现文件

#include <stdio.h>
#include <stdlib.h>
#include "LinkList.h"

// 1)
LinkList* LL_Create()
// 创建一个链接存储的线性表,初始为空表,返回llist指针。
{
    LinkList* llist=(LinkList*)malloc(sizeof(LinkList));
    llist->front=NULL;
    llist->rear=NULL;
    llist->pre=NULL;
    llist->curr=NULL;
    llist->position=0;
    llist->len=0;
    return llist;
}

// 2)	
void LL_Free(LinkList* llist)
// 释放链表的结点,然后释放llist所指向的结构。
{
    LinkNode* node=llist->front;
    LinkNode* nextnode;
    while(node){
        nextnode=node->next;
        free(node);
        node=nextnode;
    }
    free(llist);
}

// 3)	
void LL_MakeEmpty(LinkList* llist)
// 将当前线性表变为一个空表,因此需要释放所有结点。
{
    LinkNode* node=llist->front;
    LinkNode* nextnode;
    while(node){
        nextnode=node->next;
        free(node);
        node=nextnode;
    }
    llist->front=NULL;
    llist->rear=NULL;
    llist->pre=NULL;
    llist->curr=NULL;
    llist->position=0;
    llist->len=0;
}

// 4)	
int LL_Length(LinkList* llist)
// 返回线性表的当前长度。
{
    return llist->len;
}

// 5)	
bool LL_IsEmpty(LinkList* llist)
// 若当前线性表是空表,则返回true,否则返回TRUE。
{
    return llist->len==0;
}

// 6)  
bool LL_SetPosition(LinkList* llist, int i)
// 设置线性表的当前位置为i号位置。
// 设置成功,则返回true,否则返回false(线性表为空,或i不在有效的返回)。
// 假设线性表当前长度为len,那么i的有效范围为[0,len]。
{	
    int k;
    /* 若链表为空,则返回*/
    if (llist->len==0) return false;

    /*若位置越界*/
    if( i < 0 || i > llist->len)
    {	printf("LL_SetPosition(): position error");
        return false;
    }

    /* 寻找对应结点*/
    llist->curr = llist->front;
    llist->pre = NULL;
    llist->position = 0;
    for ( k = 0; k < i; k++)	{
        llist->position++;
        llist->pre = llist->curr;
        llist->curr = (llist->curr)->next;
    }
    
    /* 返回当前结点位置*/
    return true;
}

// 7)	
int LL_GetPosition(LinkList* llist)
// 获取线性表的当前位置结点的编号。
{
    return llist->position;
}

// 8)	
bool LL_NextPosition(LinkList* llist)
// 设置线性表的当前位置的下一个位置为当前位置。
// 设置成功,则返回true,否则返回false(线性表为空,或当前位置为表尾)。
{
    if (llist->position >= 0 && llist->position < llist->len)
    /* 若当前结点存在,则将其后继结点设置为当前结点*/
    {
        llist->position++;
        llist->pre = llist->curr;
        llist->curr = llist->curr->next;
        return true;
    }
    else 
        return false;
}

// 9)	
T LL_GetAt(LinkList* llist)
// 返回线性表的当前位置的数据元素的值。
{
    if(llist->curr==NULL)
    {
        printf("LL_GetAt(): Empty list, or End of the List.\n");
        LL_Free(llist);
        exit(1);
	}
    return llist->curr->data;
}

// 10)	
void LL_SetAt(LinkList* llist, T x)
// 将线性表的当前位置的数据元素的值修改为x。
{
    if(llist->curr==NULL)
    {
        printf("LL_SetAt(): Empty list, or End of the List.\n");
        LL_Free(llist);
        exit(1);
    }
    llist->curr->data=x;
}

// 11)	
bool LL_InsAt(LinkList* llist, T x)
// 在线性表的当前位置之前插入数据元素x。当前位置指针指向新数据元素结点。
// 若插入失败,返回false,否则返回true。
{	
    LinkNode *newNode=(LinkNode*)malloc(sizeof(LinkNode));
    if (newNode==NULL) return false;

    newNode->data=x;

    if (llist->len==0){
        /* 在空表中插入*/
        newNode->next=NULL;
        llist->front = llist->rear = newNode;
	}
    //当前位置为表头。
    else if (llist->pre==NULL)
    {
        /* 在表头结点处插入*/
        newNode->next = llist->front;
        llist->front = newNode;
    }
    else {  
        /* 在链表的中间位置或表尾后的位置插入*/
        newNode->next = llist->curr;
        llist->pre->next=newNode;
    }
    //插入在表尾后。
    if (llist->pre==llist->rear)
        llist->rear=newNode;
    /* 增加链表的大小*/
    llist->len++;
    /* 新插入的结点为当前结点*/
    llist->curr = newNode;
    return true;
}

// 12)	
bool LL_InsAfter(LinkList* llist, T x)
// 在线性表的当前位置之后插入数据元素x。空表允许插入。当前位置指针将指向新结点。
// 若插入失败,返回false,否则返回true。
{
    // 请在Begin-End之间补充代码,实现结点插入。
    /********** Begin *********/
    LinkNode* node = (LinkNode*)malloc(sizeof(LinkNode));
    if(node==NULL){
        return false;
    }
    node->data=x;
    if(llist->len==0){
        node->next=NULL;
        llist->front = llist->rear=node;
    }else if(llist->pre==NULL){
        node->next=llist->curr->next;
        llist->curr->next=node;
    }else{
        node->next = llist->curr->next;
        llist->curr->next=node;
    }
    if(llist->pre==llist->rear){
        llist->rear=node;
    }
    llist->len++;
    llist->curr=node;
    return true;

    /********** End **********/
}

// 13)	
bool LL_DelAt(LinkList* llist)
// 删除线性表的当前位置的数据元素结点。
// 若删除失败(为空表,或当前位置为尾结点之后),则返回false,否则返回true。
{	
    LinkNode *oldNode;
    /* 若表为空或已到表尾之后,则给出错误提示并返回*/
    if (llist->curr==NULL)
    {	
        printf("LL_DelAt(): delete a node that does not exist.\n");
        return false;
    }
    oldNode=llist->curr;
    /* 删除的是表头结点*/
    if (llist->pre==NULL)
    {	
        llist->front = oldNode->next;
    }
    /* 删除的是表中或表尾结点*/
    else if(llist->curr!=NULL){
        llist->pre->next = oldNode->next;
    }
    if (oldNode == llist->rear)	{
        /* 删除的是表尾结点,则修改表尾指针和当前结点位置值*/
        llist->rear = llist->pre;
    }

    /* 后继结点作为新的当前结点*/
    llist->curr = oldNode->next;

    /* 释放原当前结点*/
    free(oldNode);

    /* 链表大小减*/
    llist->len --;
    return true;
}

// 14)	
bool LL_DelAfter(LinkList* llist)
// 删除线性表的当前位置的后面那个数据元素。
// 若删除失败(为空表,或当前位置时表尾),则返回false,否则返回true。
{
    LinkNode *oldNode;
    /* 若表为空或已到表尾,则给出错误提示并返回*/
    if (llist->curr==NULL || llist->curr== llist->rear)
    {
        printf("LL_DelAfter():  delete a node that does not exist.\n");
        return false;
    }
    /* 保存被删除结点的指针并从链表中删除该结点*/
    oldNode = llist->curr->next;
    llist->curr->next=oldNode->next;
    
    if (oldNode == llist->rear)
        /* 删除的是表尾结点*/
        llist->rear = llist->curr;
    /* 释放被删除结点*/
    free(oldNode);
    /* 链表大小减*/
    llist->len --;
    return true;
}

// 15)	
int LL_FindValue(LinkList* llist, T x)
// 找到线性表中第一个值为x的数据元素的编号。
// 返回值-1表示没有找到,返回值>=0表示编号。
{
    LinkNode* p=llist->front;
    int idx=0;
    while(p!=NULL && p->data!=x) {
        idx++;
        p = p->next;
    }
    if (idx>=llist->len) return -1;
    else return idx;
}

// 16)	
int LL_DelValue(LinkList* llist, T x)
// 删除第一个值为x的数据元素,返回该数据元素的编号。如果不存在值为x的数据元素,则返回-1。
{
    int idx=LL_FindValue(llist, x);
    if (idx<0) return -1;
    LL_SetPosition(llist, idx);
    LL_DelAt(llist);
    return idx;
}

// 17)	
void LL_Print(LinkList* llist)
// 打印整个线性表。
{
    LinkNode* node=llist->front;
    while (node) {
        printf("%d ", node->data);
        node=node->next;
    }
    printf("\n");
}

第4关 线性链表

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stu{
    char  name[32];
    struct stu  *next;
};

/*创建链表,参数n是初始化链表时建立的数据个数
prev:指向当前结点的前一个结点
cur:指向当前结点
head:保存表头结点的指针*/
struct stu* CreatList(int n){
    int i;
    char age[12];
    struct stu *prev,*cur,*head;
    head=(struct stu*)malloc(sizeof(struct stu));
    if(head==NULL){
        printf("Can't alloc memory\n");
        return NULL;
    }
    prev=head;
    head->name[0]='\0';
    head->next=NULL;
    for(i=1;i<=n;i++){
        cur=(struct stu*)malloc(sizeof(struct stu));
        if(cur==NULL){
            printf("Can't alloc memory\n");
            return NULL;                
        }
    scanf("%s",cur->name);
    // 请在下面的Begin-End之间补充代码,插入结点。
    /********** Begin *********/


        prev->next=cur;
        prev=prev->next;

    /********** End **********/
    }
    printf("线性链表创建成功!\n");
    return head;
}
/*遍历链表,打印链表数据*/
void Print(struct stu *head){
    struct stu *cur;
    cur=head->next;
    while(cur!=NULL){
        printf("%s\n",cur->name);
        cur=cur->next;
    }
}
int main(){
    int number=3;
    char _name[32];
    struct stu *head,*cur,*fro;
    head=CreatList(number);
    if(head==NULL)
        return -1;
    Print(head);
    return 0;   
}

第5关 循环链表

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
typedef int EleType;
typedef struct CLinkNode
{
	EleType data;
	struct CLinkNode *next;
}CLinkNode,*CLinkList;
 
/*
初始化循环链表
*/
int InitCLinkList(CLinkList *list)
{
	if (list == NULL)
	{
		return ERROR;
	}
 
	int data = 0;
	CLinkNode* target = NULL;
	CLinkNode* head_node = NULL;
	printf("输入结点数据中...\n");
	while (1)
	{
		scanf("%d", &data);
		if (data == 0)
		{
			//退出循环标志,用户输入0 表示结束输入数据
			break;
		}

		if (*list == NULL)
		{
			CLinkNode* head= (CLinkNode*)malloc(sizeof(CLinkNode));
			//分配结点空间失败
			if (head == NULL)
			{
				exit(0);
			}
 
			*list = head;//链表指向头结点
 
			CLinkNode* node = (CLinkNode*)malloc(sizeof(CLinkNode));
			if (node == NULL)
			{
				exit(0);
			}
			node->data = data;
			node->next = head;
			head->next = node;
		}
		else
		{
			for (target = (*list)->next; target->next != *list; target = target->next);
			head_node = target->next;
 
			CLinkNode* node = (CLinkNode*)malloc(sizeof(CLinkNode));
			if (node == NULL)
			{
				exit(0);
			}
			node->data = data;
			node->next = head_node;
 
			target->next = node;//将新结点插入尾部
		}
 
	}
	return OK;
}
/*
往链表指定位置插入数据
list 循环链表
loc 第loc位置插入元素,loc 从1 开始计数
data 插入元素的数据域
*/
int InsertCLinkNode(CLinkList list,int loc, EleType data)
{
	if (list == NULL || loc < 1)
		return ERROR;
	/*
	循环目的:找到第loc-1位置结点
	*/
	int i = 1;
	CLinkNode* node = list;//刚开始node指向头结点
	while (node->next!=list && i < loc)
	{
		node = node->next;
		i++;
	}
	if (i == loc)
	{
		CLinkNode* new_node = (CLinkNode*)malloc(sizeof(CLinkNode));
		if (new_node == NULL)
		{
			exit(0);
		}
		new_node->data = data;
		new_node->next = node->next;//新结点指针域 指向前驱结点的后继结点
		node->next = new_node;//将新结点加入链表
	}
	else
	{
		return	ERROR;
	}
 
	return OK;
}
/*
删除指定结点,通过指针返回删除结点的数据,并保存至data
*/
int DelCLinkNode(CLinkList list,int loc, EleType* data)
{
	if (list == NULL || loc < 1)
		return ERROR;
	/*
	循环目的:找到第loc-1位置结点
	*/
	int i = 1;// 按人类的读法 i表示第i个位置 和 loc 表达意思一致
	CLinkNode* node = list;//刚开始node指向头结点
	while (node->next != list && i < loc)
	{
		node = node->next;
		i++;
	}
	//循环结束 node 指向 loc-1 位置 且 node 不能为尾结点,为什么不能为尾结点?因为不能删除 位置上没有元素的结点!
	if (i == loc && node->next != list)
	{
        // 请在下面的Begin-End之间补充代码,完成对结点的删除。
        /********** Begin *********/
        node->next=node->next->next;

            
        /********** End **********/
 
	}
	return OK;
}
/*
展示循环链表元素
*/
int ShowCLinkList(CLinkList list)
{
	if (list == NULL)
	{
		return ERROR;
	}
	CLinkNode* target = NULL;
	
	for (target = list->next; target != list; target = target->next)
		printf("%d \t",target->data);
	printf("\n");
	return OK;
}
int main(int argc, char *argv[])
{
	int flag = 0;
	CLinkList list = NULL;
	list = NULL;
	InitCLinkList(&list);
	printf("--------循环链表初始元素------\n");
	ShowCLinkList(list); 
	int loc = 2;
	int data = 0;
	DelCLinkNode(list, loc, &data);
	printf("--------删除第二个结点后------\n");
	ShowCLinkList(list); 
	return 0;
}

第6关 双向链表

#include <stdio.h>
#include <stdlib.h>
//节点结构
typedef struct line {
    struct line * prior;
    int data;
    struct line * next;
}line;
//双链表的创建函数
line* initLine(line * head);
//输出双链表的函数
void display(line * head);

int main() {
    //创建一个头指针
    line * head = NULL;
    //调用链表创建函数
    head = initLine(head);
    printf("链表结构为:");
    //输出创建好的链表
    display(head);
    //显示双链表的优点
    printf("链表中第 4 个节点的直接前驱是:%d", head->next->next->next->prior->data);
    return 0;
}
line* initLine(line * head) {
	printf("输入数据中...\n");
	int data[6]={0};
	for(int i=0;i<6;i++){
		scanf("%d",&data[i]);
	} 
    line * list = NULL;
    //创建一个首元节点,链表的头指针为head
    head = (line*)malloc(sizeof(line));
    //对节点进行初始化
    head->prior = NULL;
    head->next = NULL;
    head->data = data[0];
    //声明一个指向首元节点的指针,方便后期向链表中添加新创建的节点
    list = head;
    for (int i = 1; i <= 5; i++) {

        // 请在下面的Begin-End之间补充代码,插入结点,其中结点数据为data[i]。
        /********** Begin *********/
        line *node = (line*)malloc(sizeof(line));
        node->data=data[i];
        node->next=NULL;
        node->prior=list;
        list->next=node;
        list=node;

        /********** End **********/
    }
    //返回新创建的链表
    return head;
}
void display(line * head) {
    line * temp = head;
    while (temp) {
        //如果该节点无后继节点,说明此节点是链表的最后一个节点
        if (temp->next == NULL) {
            printf("%d\n", temp->data);
        }
        else {
            printf("%d <-> ", temp->data);
        }
        temp = temp->next;
    }
}

第7关 一元多项式的表示及相加

#include <stdio.h>
#include <stdlib.h>
typedef struct PLnode{
    //数据域,coef 表示系数,expn 表示指数
    float coef;
    int expn;
    //指针域
    struct PLnode *next;
}PLnode,*PLinkList;

//一元多项式的链表表示创建函数,输入 m 项的系数和指数,建立表示一元多项式的有序链表L
void creatpolyn(PLinkList L, int m){
    int i;
    float coef;
    int expn;
    PLinkList tail,n;
    L->coef = m;
    L->expn = -1;
    tail = L;
    for(i=1 ; i<=m ; i++){
         n = (PLinkList)malloc(sizeof(PLnode));
         scanf("%f",&coef);
         scanf("%d",&expn);
         n->coef = coef;
         n->expn = expn;
         n->next = NULL;
         tail->next = n;
         tail = n;
    }
}
//完成多项式相加运算,即 Lc = La + Lb,并销毁一元多项式 Lb
PLinkList addpolyn(PLinkList La , PLinkList Lb){
    int x,len;
    float y;
    PLinkList Lc,pa,pb,pc,u;
    Lc = La;
    len = 0;
    pc = Lc;
    //另pa,pb 指向La 、Lb 的首元结点
    pa = La->next;
    pb = Lb->next;
    //通过 pa,pb 遍历链表 La、Lb,只有两指针同时存在时,才需要讨论
    while(pa && pb){
        x = pa->expn-pb->expn;
        //判断pa 所指结点的指数与pb 所指结点指数的大小关系
        if(x<0){
            //如果小,则找去 qa 结点到Lc 上
            pc = pa;
            len++;
            pa = pa->next;
        }
        //如果相等,则判断两结点的系数和是否为0
        else if(x == 0){
            // 请在下面的Begin-End之间补充代码,完成一元多项式的相加。
            /********** Begin *********/

            pa->coef=pa->coef+pb->coef;
            pc=pa;
            len++;
            pa=pa->next;
            pb=pb->next;


            /********** End **********/
        }
        //如果pb 所指结点指数值小,则摘取pb所指结点到 LC链表上
        else{
            u = pb->next;
            pb->next= pa;
            pc->next=pb;
            pc = pb;
            len++;
            pb = u;
        }
    }
    //由于是在 La 上进行一元多项式的加和,所以如果运行过程 pa 不再有结点,而pb 上有,则需要将pb剩余结点链接到 Lc 上
    if(pb){
        pc->next = pb;
    }
    //计算 Lc 的长度
    while(pc){
        pc = pc->next;
        if(pc){
            len++;
        }
    }
    //Lc 的头结点中记录Lc 链表的长度
    Lc->coef = len;
    //加和完成的同时,释放Lb 结点
    free(Lb);
    return Lc;
}
//根据链表存储信息。输出结点 q
void printpoly(PLinkList q){
    if(q->expn == 0){
        printf("%.0f",q->coef);
    }
    else if(q->expn == 1){
        if(q->coef == 1){
            printf("x");
        }
        else if (q->coef == -1){
            printf("-x");
        }
        else{
            printf("%.0f",q->coef);
            printf("x");
        }
    }
    else if (q->coef == 1){
        printf("x^%d",q->expn);
    }
    else if(q->coef == -1){
        printf("-x^%d",q->expn);
    }
    else{
        printf("%.0fx^%d",q->coef,q->expn);
    }
}
//输出一元多项式L
void printpolyn(PLinkList L){
    int n;
    PLinkList p;
    p = L->next;
    n = 0;
    while(p){
        n++;
        if(n == 1){
            printpoly(p);
        }else if(p->coef>0){
            printf("+");
            printpoly(p);
        }else{
            printpoly(p);
        }
        p = p->next;
    }
}
int main(){
    PLinkList La,Lb,Lc;
    int m,n;
    //根据 n 的值,创建链表La
    scanf("%d",&n);
    La = (PLinkList)malloc(sizeof(PLnode));
    creatpolyn(La,n);
    //根据 m 的值,创建 Lb
    scanf("%d",&m);
    Lb = (PLinkList)malloc(sizeof(PLnode));
    creatpolyn(Lb,m);
    //输出La和Lb
    printf("La=");
    printpolyn(La);
    printf("\nLb=");
    printpolyn(Lb);
    //计算La+Lb,结果保存在 Lc中
    printf("\n计算结果为:");
    Lc = addpolyn(La,Lb);
    printf("\nLc=");
    printpolyn(Lc);
    return 0;
}

串类型的定义

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

串的表示和实现

第1关 定长存储表示

#include<stdio.h>
int main()
{
    // 创建数组,内容为"this is my string"
    // 请在下方填写你的代码
    /******** begin *******/





    char str[]="this is my string";
    printf("%s",str);

    /******* end *********/
    return 0;
}

第2关 堆分配存储表示

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char * a1 = NULL;
    char * a2 = NULL;
    a1 = (char*)malloc(10 * sizeof(char));
    strcpy(a1, "Hello");//将字符串"data.bian"复制给a1
    a2 = (char*)malloc(10 * sizeof(char));
    strcpy(a2, "World");
    int lengthA1 = strlen(a1);//a1串的长度
    int lengthA2 = strlen(a2);//a2串的长度
    /**** 请在下方补全代码 ************/
 /************* begin *********************/
 
 
 
     a1 = strcat(a1,a2);
 
 
 
 /************* end **********************/
    //串的末尾要添加 \0,避免出错
    a1[lengthA1 + lengthA2] = '\0';
    printf("%s", a1);
    //用完动态数组要立即释放
    free(a1);
    free(a2);
    return 0;
}

第3关 块链存储表示

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define linkNum 3//全局设置链表中节点存储数据的个数
typedef struct Link {
    char a[linkNum]; //数据域可存放 linkNum 个数据
    struct Link * next; //代表指针域,指向直接后继元素
}link; // nk为节点名,每个节点都是一个 link 结构体
link * initLink(link * head, char * str);
void displayLink(link * head);
int main()
{
    link * head = NULL;
    head = initLink(head, "hello.world");
    displayLink(head);
    return 0;
}
//初始化链表,其中head为头指针,str为存储的字符串
link * initLink(link * head, char * str) {
    int length = strlen(str);
    //根据字符串的长度,计算出链表中使用节点的个数
    int num = length/linkNum;
    if (length%linkNum) {
        num++;
    }
    //创建并初始化首元节点
    head = (link*)malloc(sizeof(link));
    head->next = NULL;
    link *temp = head;
    //初始化链表
/** 请在此处填写你的代码 ****/
/************************** begin ******************/
    for(int i=0;i<3;i++){
        temp->a[i]=str[i];
    }
    int cnt=1;
    for(int i=3;i<strlen(str);){
        link* node = (link*)malloc(sizeof(link));
        node->next=NULL;
        for(int j=0;j<3;j++,i++){
            node->a[j]=str[i];
            if(i==strlen(str)){
                for(int k=j;k<3;k++){
                    node->a[k]='#';
                }
            }
        }
        temp->next=node;
        temp=node;
        cnt++;
    }




/*************************** end *******************/
    return head;
}
//输出链表
void displayLink(link * head) {
    link * temp = head;
    while (temp) {
        for (int i = 0; i < linkNum; i++) {
            printf("%c", temp->a[i]);
        }
        temp = temp->next;
    }
}

串的模式匹配算法

第1关 普通模式匹配(BF)算法

#include <stdio.h>
#include <string.h>
//串普通模式匹配算法的实现函数,其中 B是伪主串,A是伪子串
const int N = 1000010;
int nextt[N];
void getnext(char *p)
{
	int lenp=strlen(p);
	nextt[0]=-1;
	int k=-1;
	int j=0;
	while(j<lenp-1)
	{
		if(k==-1||p[j]==p[k])
		{
			j++;
			k++;
			if(p[j]!=p[k])
			{
				nextt[j]=k;
			}
			else
		    	nextt[j]=nextt[k]; 
		}
		else
		{
			k=nextt[k];
		}
	}
	return;
}
int mate(char * s,char *p){
    /** 请在此处填写代码 **/
    /********** Begin *********/
    getnext(p);
	int i=0;
	int j=0;
	int lens=strlen(s);
	int lenp=strlen(p);
	while(i<lens&&j<lenp)
	{
		if(j==-1||s[i]==p[j])
		{
			j++;
			i++;
		}
		else
		{
			
			j=nextt[j]; 
		}
	}
	if(j==lenp)
	return i-j+1; 
	else
	return -1; 
    /********** End **********/
}
int main() {
    int number=mate("ababcabcacbab", "abcac");
    printf("%d",number);
    return 0;
}

第2关 快速模式匹配(KMP)算法

#include <stdio.h>
#include <string.h>
void Next(char*T,int *next){
    int i=1;
    next[1]=0;
    int j=0;
    while (i<strlen(T)) {
        if (j==0||T[i-1]==T[j-1]) {
            i++;
            j++;
            next[i]=j;
        }else{
            j=next[j];
        }
    }
}
int KMP(char * S,char * T){
/** 实现KMP算法, 若匹配返回匹配字符串长度,若不匹配返回 -1 **/

/*************** begin *******************/
    int next[strlen(T) + 1];
    Next(T, next);

    int i = 1, j = 1;
    while (i <= strlen(S) && j <= strlen(T)) {
        if (j == 0 || S[i - 1] == T[j - 1]) {
            i++;
            j++;
        } else {
            j = next[j];
        }
    }

    if (j > strlen(T)) {
        return i - strlen(T);
    } else {
        return -1;
    }

/*************** end *********************/
}
int main() {

    char a[1000], b[100];
    scanf("%s %s", a, b);
    int i = KMP(a, b);
    printf("%d",i);
    return 0;
}

数据结构与算法 - 栈

第1关 实现一个顺序存储的栈


//顺序存储的栈 实现文件
/
#include <stdio.h>
#include <stdlib.h>
#include "SeqStack.h"

SeqStack* SS_Create(int maxlen)
{
	SeqStack* ss=(SeqStack*)malloc(sizeof(SeqStack));
	ss->data=(T*)malloc(maxlen*sizeof(T));
	ss->top=-1;
	ss->max=maxlen;
	return ss;
}

/*释放一个栈*/
void SS_Free(SeqStack* ss)
{
	free(ss->data);
	free(ss);
}

/*清空一个栈*/
void SS_MakeEmpty(SeqStack* ss)
{
	ss->top=-1;
}

/*判断栈是否为满*/
bool SS_IsFull(SeqStack* ss)
{
	/*请在BEGIN和END之间实现你的代码*/
    /*****BEGIN*****/
    return ss->top==ss->max-1;
    /******END******/
}

/*判断栈是否为空*/
bool SS_IsEmpty(SeqStack* ss)
{
	/*请在BEGIN和END之间实现你的代码*/
    /*****BEGIN*****/
    return ss->top==-1;
    /******END******/
}

/*获取栈元素个数*/
int SS_Length(SeqStack* ss)
{
	/*请在BEGIN和END之间实现你的代码*/
    /*****BEGIN*****/
    return ss->top+1;
    /******END******/
}

/*将x进栈,满栈则无法进栈(返回false)*/
bool SS_Push(SeqStack* ss, T x)
{
	/*请在BEGIN和END之间实现你的代码*/
    /*****BEGIN*****/
    if(SS_IsFull(ss)){
        return false;
    }
    ss->top++;
    ss->data[ss->top]=x;
    return true;
    /******END******/
}

/*出栈,出栈的元素放入item,空栈则返回false*/
bool SS_Pop(SeqStack* ss, T &item)
{
	/*请在BEGIN和END之间实现你的代码*/
    /*****BEGIN*****/
    if(SS_IsEmpty(ss)){
        return false;
    }
    item=ss->top;
    ss->top--;
    return true;
    /******END******/
}

/*获取栈顶元素放入item中,空栈则返回false*/
bool SS_Top(SeqStack* ss, T & item)
{
	if (SS_IsEmpty(ss)) {
		return false;
	}
	item = ss->data[ss->top];
	return true;
}

/*从栈底到栈顶打印出所有元素*/
void SS_Print(SeqStack* ss)
{
	if (SS_IsEmpty(ss)) {
		printf("stack data: Empty!\n");
		return;
	}
	printf("stack data (from bottom to top):");
	int curr=0;
	while(curr<=ss->top) {
		printf(" %d", ss->data[curr]);
		curr++;
	}
	//printf("\n");
}

第2关 实现一个链接存储的栈


// 链接存储的栈实现文件

#include <stdio.h>
#include <stdlib.h>
#include "LnkStack.h"

/*创建栈*/
LinkStack* LS_Create()
{
    LinkStack* ls=(LinkStack*)malloc(sizeof(LinkStack));
    ls->top = NULL;
    ls->len = 0;
    return ls;
}

/*释放栈*/
void LS_Free(LinkStack* ls)
{
    LNode* curr = ls->top;
    while(curr) {
        LNode* next = curr->next;
        free(curr);
        curr=next;
    }
    free(ls);
}

/*将栈变为空栈*/
void LS_MakeEmpty(LinkStack* ls)
{
    LNode* curr = ls->top;
    while(curr) {
        LNode* next = curr->next;
        free(curr);
        curr=next;
    }
    ls->top = NULL;
    ls->len = 0;
}

/*判断栈是否为空*/
bool LS_IsEmpty(LinkStack* ls)
{
    // 请在这里补充代码,完成本关任务
    /********** Begin *********/
    return ls->len==0;

    /********** End **********/
}

/*获取栈的长度*/
int LS_Length(LinkStack* ls)
{
    // 请在这里补充代码,完成本关任务
    /********** Begin *********/
    return ls->len;
    /********** End **********/
}

/*将x进栈*/
void LS_Push(LinkStack* ls, T x)
{
    // 请在这里补充代码,完成本关任务
    /********** Begin *********/
    LNode* node = (LNode*)malloc(sizeof(LNode));
    node->data=x;
    node->next=ls->top;
    ls->top=node;
    ls->len++;
    /********** End **********/
}

/*出栈。出栈元素放入item;如果空栈,将返回false*/
bool LS_Pop(LinkStack* ls, T& item)
{
    // 请在这里补充代码,完成本关任务
    /********** Begin *********/
    if(LS_IsEmpty(ls)){
        return false;
    }
    LNode *p = ls->top;
    item=ls->top->data;
    ls->top=ls->top->next;
    ls->len--;
    free(p);
    return true;
    /********** End **********/
}

/*读栈顶元素放入item。如果空栈,将返回false*/
bool LS_Top(LinkStack* ls, T& item)
{
    // 请在这里补充代码,完成本关任务
    /********** Begin *********/
    if(LS_IsEmpty(ls)){
        return false;
    }
    item=ls->top->data;
    return true;

    /********** End **********/
}

/*从栈顶到栈底打印各结点数据*/
void LS_Print(LinkStack* ls)
{
    if (ls->len==0){ 
        printf("The stack: Empty!");
        return;
    }
    printf("The stack (from top to bottom):");
    LNode* curr=ls->top;
    while(curr) {
        printf(" %d", curr->data);
         
        curr=curr->next;
    }
   // printf("\n");
}

数制转换

第1关 十进制转为八进制

/*************************************************************
    date: March 2021
    copyright: Bei Gua(北瓜)
    DO NOT distribute this code.
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "SeqStack.h"

#define Max 100
typedef int T;



//该函数实现十进制向八进制转换,a为待转为八进制的数
void decimal_octal(int a){
	SeqStack* ss=SS_Create(Max);  //创建一个空栈
	
	 /*****BEGIN*****/

    int b=a*8;
    while(b/8!=0){
        SS_Push(ss,a%8);
        b/=8;a/=8;
    }
    /******END******/
	SS_Print(ss);
	SS_Free(ss);
}


/*创建一个栈*/
SeqStack* SS_Create(int maxlen)
{
    SeqStack* ss=(SeqStack*)malloc(sizeof(SeqStack));
    ss->data=(T*)malloc(maxlen*sizeof(T));
    ss->top=-1;
    ss->max=maxlen;
    return ss;
}
/*释放一个栈*/
void SS_Free(SeqStack* ss)
{
    free(ss->data);
    free(ss);
}
/*清空一个栈*/
void SS_MakeEmpty(SeqStack* ss)
{
    ss->top=-1;
}
bool SS_IsFull(SeqStack* ss)
// 判断栈是否为满。为满返回true,否则返回false。
{
    return ss->top+1>=ss->max;
  
}
bool SS_IsEmpty(SeqStack* ss)
// 判断栈是否为空。为空返回true,否则返回false。
{
    return ss->top<0;
}
int SS_Length(SeqStack* ss)
// 获取栈元素个数
{
   
    return ss->top+1;
}
bool SS_Push(SeqStack* ss, T x)
// 将元素x进栈,若满栈则无法进栈,返回false,否则返回true
{
    if (SS_IsFull(ss)) {
        return false;
    }
    ss->top++;
    ss->data[ss->top]=x;
    return true;
    
}
bool SS_Pop(SeqStack* ss, T &item)
// 出栈的元素放入item。若出栈成功(栈不为空),则返回true;否则(空栈),返回false。
{
    
    if (SS_IsEmpty(ss)) {
        return false;
    }
    item = ss->data[ss->top];
    ss->top--;
    return true;
   
}
/*获取栈顶元素放入item中,空栈则返回false*/
bool SS_Top(SeqStack* ss, T & item)
{
    if (SS_IsEmpty(ss)) {
        return false;
    }
    item = ss->data[ss->top];
    return true;
}
/*从栈底到栈顶打印出所有元素*/
void SS_Print(SeqStack* ss)
{
    if (SS_IsEmpty(ss)) {
        printf("stack data: Empty!\n");
        return;
    }
    int curr=ss->top;
    while(curr>=0) {
        printf("%d", ss->data[curr]);
        curr--;
    }
    //printf("\n");
}

括号匹配的检验

第1关 括号匹配

 /*************************************************************
    date: March 2021
    copyright: Bei Gua(北瓜)
    DO NOT distribute this code.
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "SeqStack.h"
#include <string.h>

#define Max 100




//该函数实现括号匹配判断
int matching(char* str){
	SeqStack* ss=SS_Create(Max);  //创建一个空栈
	
	 /*****BEGIN*****/
    char item;
     for(int i=0;i<strlen(str);i++){
         if(str[i]=='(' || str[i]=='[')
         SS_Push(ss, str[i]);
         if((ss->data[ss->top]=='(' && str[i]==')' )|| (ss->data[ss->top]=='[' && str[i]==']'))
         SS_Pop(ss,item);
     }
     if(SS_IsEmpty(ss))
     return 1;
     else
     return 0;

    /******END******/
	
	SS_Free(ss);
}


/*创建一个栈*/
SeqStack* SS_Create(int maxlen)
{
    SeqStack* ss=(SeqStack*)malloc(sizeof(SeqStack));
    ss->data=(T*)malloc(maxlen*sizeof(T));
    ss->top=-1;
    ss->max=maxlen;
    return ss;
}
/*释放一个栈*/
void SS_Free(SeqStack* ss)
{
    free(ss->data);
    free(ss);
}
/*清空一个栈*/
void SS_MakeEmpty(SeqStack* ss)
{
    ss->top=-1;
}
bool SS_IsFull(SeqStack* ss)
// 判断栈是否为满。为满返回true,否则返回false。
{
    return ss->top+1>=ss->max;
  
}
bool SS_IsEmpty(SeqStack* ss)
// 判断栈是否为空。为空返回true,否则返回false。
{
    return ss->top<0;
}
int SS_Length(SeqStack* ss)
// 获取栈元素个数
{
   
    return ss->top+1;
}
bool SS_Push(SeqStack* ss, T x)
// 将元素x进栈,若满栈则无法进栈,返回false,否则返回true
{
    if (SS_IsFull(ss)) {
        return false;
    }
    ss->top++;
    ss->data[ss->top]=x;
    return true;
    
}
bool SS_Pop(SeqStack* ss, T &item)
// 出栈的元素放入item。若出栈成功(栈不为空),则返回true;否则(空栈),返回false。
{
    
    if (SS_IsEmpty(ss)) {
        return false;
    }
    item = ss->data[ss->top];
    ss->top--;
    return true;
   
}
/*获取栈顶元素放入item中,空栈则返回false*/
bool SS_Top(SeqStack* ss, T & item)
{
    if (SS_IsEmpty(ss)) {
        return false;
    }
    item = ss->data[ss->top];
    return true;
}
/*从栈顶到栈底打印出所有元素*/
void SS_Print(SeqStack* ss)
{
    if (SS_IsEmpty(ss)) {
        printf("stack data: Empty!\n");
        return;
    }
    int curr=ss->top;
    while(curr>=0) {
        printf("%d", ss->data[curr]);
        curr--;
    }
    //printf("\n");
}

迷宫求解

第1关 迷宫求解(栈)

 /*************************************************************
    date: March 2021
    copyright: Bei Gua(北瓜)
    DO NOT distribute this code.
**************************************************************/
//顺序存储的栈 实现文件
/
#include <stdio.h>
#include <stdlib.h>
#include "SeqStack.h"


//得到迷宫路径,maze为迷宫地图,1表示通路,0表示墙
void GetPath(SeqStack* ss,int maze[][6]){
	
	/****begin*******/
	    int dx[] = {1, 0, -1, 0}; // 右,下,左,上
    int dy[] = {0, 1, 0, -1};
    int startX = 0, startY = 0;
    int endX = 5, endY = 5;
// 起始位置入栈
SS_Push(ss, startX, startY);

    while (!SS_IsEmpty(ss)) {
        int currentX, currentY;
        SS_Top(ss, currentX, currentY);

        if (currentX == endX && currentY == endY) {
            // 寻找路径
            SS_Print(ss);
            return;
        }

        bool found = false;
        for (int i = 0; i < 4; i++) {
            int newX = currentX + dx[i];
            int newY = currentY + dy[i];

            if (newX >= 0 && newX < 6 && newY >= 0 && newY < 6 && maze[newX][newY] == 1) {
                maze[newX][newY] = 0; // 已走过的进行标记
                SS_Push(ss, newX, newY);
                found = true;
                break;
            }
        }

        if (!found) {
            // 没有可走的路
            SS_Pop(ss, currentX, currentY);
        }
    }
	
	/*******end******/
	SS_Print(ss);
}




/*创建一个栈*/
SeqStack* SS_Create(int maxlen)
{
    SeqStack* ss=(SeqStack*)malloc(sizeof(SeqStack));
    ss->col=(T*)malloc(maxlen*sizeof(T));
    ss->row=(T*)malloc(maxlen*sizeof(T));
    ss->top=-1;
    ss->max=maxlen;
    return ss;
}
/*释放一个栈*/
void SS_Free(SeqStack* ss)
{
    free(ss->row);
    free(ss->col);
    free(ss);
}
/*清空一个栈*/
void SS_MakeEmpty(SeqStack* ss)
{
    ss->top=-1;
}
bool SS_IsFull(SeqStack* ss)
// 判断栈是否为满。为满返回true,否则返回false。
{
    
    return ss->top+1>=ss->max;
    
}
bool SS_IsEmpty(SeqStack* ss)
// 判断栈是否为空。为空返回true,否则返回false。
{
    
    return ss->top<0;
}
int SS_Length(SeqStack* ss)
// 获取栈元素个数
{
    return ss->top+1;
}
bool SS_Push(SeqStack* ss, T x,T y)
// 将元素x进栈,若满栈则无法进栈,返回false,否则返回true
{
    // 请在这里补充代码,完成本关任务
    if (SS_IsFull(ss)) {
        return false;
    }
    ss->top++;
    
    ss->row[ss->top]=x;
    ss->col[ss->top]=y;
    return true;
}
bool SS_Pop(SeqStack* ss, T &x,T &y)
// 出栈的元素放入item。若出栈成功(栈不为空),则返回true;否则(空栈),返回false。
{
    if (SS_IsEmpty(ss)) {
        return false;
    }
    x= ss->row[ss->top];
    y= ss->row[ss->top];
    ss->top--;
    return true;
}
/*获取栈顶元素放入item中,空栈则返回false*/
bool SS_Top(SeqStack* ss,T &x,T &y)
{
    if (SS_IsEmpty(ss)) {
        return false;
    }
    x= ss->row[ss->top];
    y= ss->col[ss->top];
    return true;
}
/*从栈底到栈顶打印出所有元素*/
void SS_Print(SeqStack* ss)
{
    if (SS_IsEmpty(ss)) {
        printf("stack data: Empty!\n");
        return;
    }
    
    int curr=0;
    while(curr<=ss->top) {
        printf("(%d,%d)", ss->row[curr],ss->col[curr]);
        curr++;
    }
}

栈与递归的实现

第2关 栈与递归的转换

  /*************************************************************
    date: March 2021
    copyright: Bei Gua(北瓜)
    DO NOT distribute this code.
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "SeqStack.h"

#define Max 100
typedef int T;

//在此补全函数,计算n!
int fun(int n){
	SeqStack* ss=SS_Create(Max);  //创建一个空栈
	ss->top=-1;
	/*****BEGIN*****/
    int result = 1;
    int item = 1;
    for(int i = 1; i <= n; i ++){
        SS_Push(ss, i);
    }        
    while(!SS_IsEmpty(ss))
    {
        SS_Pop(ss,item);
        result*=item;
    }
    return result;
    /******END******/
}


/*创建一个栈*/
SeqStack* SS_Create(int maxlen)
{
    SeqStack* ss=(SeqStack*)malloc(sizeof(SeqStack));
    ss->data=(T*)malloc(maxlen*sizeof(T));
	ss->fn=(T*)malloc(maxlen*sizeof(T));
    ss->top=-1;
    ss->max=maxlen;
    return ss;
}
/*释放一个栈*/
void SS_Free(SeqStack* ss)
{
    free(ss->data);
    free(ss);
}
/*清空一个栈*/
void SS_MakeEmpty(SeqStack* ss)
{
    ss->top=-1;
}
bool SS_IsFull(SeqStack* ss)
// 判断栈是否为满。为满返回true,否则返回false。
{
    return ss->top+1>=ss->max;
  
}
bool SS_IsEmpty(SeqStack* ss)
// 判断栈是否为空。为空返回true,否则返回false。
{
    return ss->top<0;
}
int SS_Length(SeqStack* ss)
// 获取栈元素个数
{
   
    return ss->top+1;
}
bool SS_Push(SeqStack* ss, T x)
// 将元素x进栈,若满栈则无法进栈,返回false,否则返回true
{
    if (SS_IsFull(ss)) {
        return false;
    }
    ss->top++;
    ss->data[ss->top]=x;
    return true;
    
}
bool SS_Pop(SeqStack* ss, T &item)
// 出栈的元素放入item。若出栈成功(栈不为空),则返回true;否则(空栈),返回false。
{
    
    if (SS_IsEmpty(ss)) {
        return false;
    }
    item = ss->data[ss->top];
    ss->top--;
    return true;
   
}
/*获取栈顶元素放入item中,空栈则返回false*/
bool SS_Top(SeqStack* ss, T & item)
{
    if (SS_IsEmpty(ss)) {
        return false;
    }
    item = ss->data[ss->top];
    return true;
}
/*从栈底到栈顶打印出所有元素*/
void SS_Print(SeqStack* ss)
{
    if (SS_IsEmpty(ss)) {
        printf("stack data: Empty!\n");
        return;
    }
    int curr=ss->top;
    while(curr>=0) {
        printf("%d", ss->data[curr]);
        curr--;
    }
    //printf("\n");
}

数据结构与算法 - 队列

第1关 实现一个顺序存储的队列


// 循环顺序的队列实现文件
/
#include <stdio.h>
#include <stdlib.h>
#include "SeqQueue.h"

SeqQueue* SQ_Create(int maxlen)
// 创建顺序队列, 队列最多存储maxlen个队列元素。
{
    SeqQueue* sq=(SeqQueue*)malloc(sizeof(SeqQueue));
    sq->data=(T*)malloc(sizeof(T)*(maxlen+1));
    sq->front=sq->rear=0;
    sq->max=maxlen+1;
    return sq;
}

void SQ_Free(SeqQueue* sq)
// 释放队列空间,以删除队列。
{
    free(sq->data);
    free(sq);
}

void SQ_MakeEmpty(SeqQueue* sq)
// 将队列置空。
{
    sq->front=0;
    sq->rear=0;
}

bool SQ_IsEmpty(SeqQueue* sq)
// 判断队列是否为空,为空返回true,否则返回false。
{
    // 请在Begin-End之间补充代码,完成队列是否为空的判断。
    /********** Begin *********/
    return sq->front==sq->rear;

    /********** End **********/
}

bool SQ_IsFull(SeqQueue* sq)
// 判断队列是否为满。为满返回true,否则返回false。
{
    // 请在Begin-End之间补充代码,完成队列是否为满的判断。
    /********** Begin *********/
    return sq->rear==sq->max-1;

    /********** End **********/
}

int SQ_Length(SeqQueue* sq)
// 队列长度。
{
    // 请在Begin-End之间补充代码,获取队列长度。
    /********** Begin *********/
    return sq->rear-sq->front;

    /********** End **********/
}

bool SQ_In(SeqQueue* sq, T x)
// 将x入队。若入队失败(队列满),则返回false,否则返回true。
{
    // 请在Begin-End之间补充代码,将 x 入队。
    /********** Begin *********/
    if(SQ_IsFull(sq)){
        return false;
    }
    sq->data[sq->rear++]=x;
    return true;
    /********** End **********/
}

bool SQ_Out(SeqQueue* sq, T& item)
// 从队列sq出队一个元素,返回时item为出队的元素的值。若出队成功(队列不为空),则返回true,否则(队列空),返回false,此时item不会返回有效值。
{
    // 请在Begin-End之间补充代码,完成元素出队操作。
    /********** Begin *********/
    if(SQ_IsEmpty(sq)){
        return false;
    }
    item=sq->data[sq->front];
    for(int i=sq->front+1;i<sq->rear;i++){
        sq->data[i-1]=sq->data[i];
    }
    sq->rear--;
    return true;
    /********** End **********/
}

bool SQ_Head(SeqQueue* sq, T& head)
// 获取队列头结点元素,返回时head保存头结点元素。
// 若获取失败(队列空),则返回值为false,否则返回值为true。
{
    if ( SQ_IsEmpty(sq) ){
        return false;
    }
    else {
        head = sq->data[sq->front];
        return true;
    }
}

void SQ_Print(SeqQueue* sq)
// 依次打印出队列中的每个元素。
{
    int i=sq->front;
    if (SQ_IsEmpty(sq)) {
        printf("queue is emtpy");
        return;
    }
    for (i=sq->front; i!=sq->rear; i=(i+1)%sq->max) {
        printf("%d  ", sq->data[i]);
    }
    printf("\n");
}

第2关 实现一个链接存储的队列

#include <stdio.h>
#include <stdlib.h>
#include "CLnkQueue.h"

LNode* CLQ_Create()
// 创建一个队列
{
    LNode* rear=(LNode*)malloc(sizeof(LNode));
    rear->data = 0;
    rear->next = rear;
    return rear;
}
void CLQ_Free(LNode* rear)
// rear指向尾结点
{
    CLQ_MakeEmpty(rear);
    free(rear);
}

void CLQ_MakeEmpty(LNode* & rear)
// rear指向尾结点
// 将队列变为空队列
{
    T item;
    while(!CLQ_IsEmpty(rear))
        CLQ_Out(rear,item);
}

bool CLQ_IsEmpty(LNode* rear)
// 判断队列是否为空
{
    // 请在这里补充代码,完成本关任务

    return rear->next->data==0;
    //return rear->next->next==rear->next;

}

int CLQ_Length(LNode* rear)
// 返回队列长度,rear指向尾结点
{
    // 请在这里补充代码,完成本关任务

    return rear->next->data;

}

void CLQ_In(LNode* & rear, T x)
// 入队列, 新结点加入链表尾部。rear指向尾结点
{
    // 请在这里补充代码,完成本关任务

    LNode*node=(LNode*)malloc(sizeof(LNode));
    node->data=x;
    node->next=rear->next;
    rear->next=node;
    rear=node;
    rear->next->data++;

}

bool CLQ_Out(LNode* & rear, T& item)
// 出队列。空队列时,返回值为false。rear指向尾结点
{
    if(CLQ_IsEmpty(rear)){
        return false;
    }
    if(rear->next->next==rear){
        LNode*node=rear;
        item=rear->data;
        rear->next->next=rear->next;
        rear=rear->next;
        free(node);
    }else{
        item=rear->next->next->data;
        LNode*node=rear->next->next;
        rear->next->next=node->next;
        free(node);

    }
    rear->next->data--;
    return true;

}

bool CLQ_Head(LNode* rear, T& item)
// rear指向尾结点
// 获取队列头。空队列时返回值为false。
{
    if (CLQ_IsEmpty(rear))
        return false;

    item = rear->next->next->data;
    return true;
}
void CLQ_Print(LNode* rear)
// 打印队列
{
    if (CLQ_IsEmpty(rear))  {
        printf("The queue is: empty. \n");
        return;
    }
    LNode* node=rear->next->next;
    do {
        printf("%d  ", node->data);
        node = node->next;
    }   while (node != rear->next);
    //printf("\n");
}


矩阵的压缩存储

第2关 三元组顺序表

#include<stdio.h>
#define number 3
typedef struct {
    int i,j;
    int data;
}triple;
typedef struct {
    triple data[number];
    int n,m,num;
}TSMatrix;
//输出存储的稀疏矩阵
void display(TSMatrix M);
int main() {
    TSMatrix M;
    M.m=3;
    M.n=3;
    M.num=3;

    M.data[0].i=1;
    M.data[0].j=1;
    M.data[0].data=1;

    M.data[1].i=2;
    M.data[1].j=3;
    M.data[1].data=5;

    M.data[2].i=3;
    M.data[2].j=1;
    M.data[2].data=3;
    display(M);
    return 0;
}
void display(TSMatrix M){
/*** 请在下方填写你的代码 *********/
/************* begin **************/

    for(int i=1;i<=number;i++){
        for(int j=1;j<=number;j++){
            bool ok=false;
            for(int k=0;k<M.num;k++){
                if(M.data[k].i==i&&M.data[k].j==j){
                    printf("%d ",M.data[k].data);
                    ok=true;
                }
            }
            if(ok){
                continue;
            }
            printf("%d ",0);
        }
        printf("\n");
    }

/************** end ***************/
} 

第3关 行逻辑链接的顺序表

#include <stdio.h>
#define MAXSIZE 12500
#define MAXRC 100
#define ElemType int
typedef struct
{
    int i,j;//行,列
    ElemType e;//元素值
}Triple;

typedef struct
{
    Triple  data[MAXSIZE+1];
    int rpos[MAXRC+1];//每行第一个非零元素在data数组中的位置
    int mu,nu,tu;//行数,列数,元素个数
}RLSMatrix;
//矩阵的输出函数
void display(RLSMatrix M){
    for(int i=1;i<=M.mu;i++){
        for(int j=1;j<=M.nu;j++){
            int value=0;
            if(i+1 <=M.mu){
                for(int k=M.rpos[i];k<M.rpos[i+1];k++){
                    if(i == M.data[k].i && j == M.data[k].j){
                        printf("%d ",M.data[k].e);
                        value=1;
                        break;
                    }
                }
                if(value==0){
                        printf("0 ");
                    }
            }else{
/*** 请在下方填写你的代码 *********/
/************* begin **************/


                if(i == M.data[M.tu].i && j == M.data[M.tu].j){
                        printf("%d ",M.data[M.tu].e);
                        value=1;
                }






/************** end ***************/
                if(value==0){
                    printf("0 ");
                }
            }

        }
        printf("\n");
    }
}
int main(int argc, char* argv[])
{
    RLSMatrix M;

    M.tu = 4;
    M.mu = 3;
    M.nu = 4;

    M.rpos[1] = 1;
    M.rpos[2] = 3;
    M.rpos[3] = 4;

    M.data[1].e = 3;
    M.data[1].i = 1;
    M.data[1].j = 2;

    M.data[2].e = 5;
    M.data[2].i = 1;
    M.data[2].j = 4;

    M.data[3].e = 1;
    M.data[3].i = 2;
    M.data[3].j = 3;

    M.data[4].e = 2;
    M.data[4].i = 3;
    M.data[4].j = 1;
    //输出矩阵
    display(M);
    return 0;
}

第4关 十字链表法

#include<stdio.h>
#include<stdlib.h>
typedef struct OLNode
{
    int i, j, e; //矩阵三元组i代表行 j代表列 e代表当前位置的数据
    struct OLNode *right, *down; //指针域 右指针 下指针
}OLNode, *OLink;
typedef struct
{
    OLink *rhead, *chead; //行和列链表头指针
    int mu, nu, tu;  //矩阵的行数,列数和非零元的个数
}CrossList;
CrossList CreateMatrix_OL(CrossList M);
void display(CrossList M);
int main()
{
    CrossList M;
    M.rhead = NULL;
    M.chead = NULL;
    M = CreateMatrix_OL(M);
    printf("输出矩阵M:\n");
    display(M);
    return 0;
}
CrossList CreateMatrix_OL(CrossList M)
{
    int m, n, t;
    int i, j, e;
    OLNode *p, *q;
    printf("输入矩阵的行数、列数和非0元素个数:");
    scanf("%d%d%d", &m, &n, &t);
    M.mu = m;
    M.nu = n;
    M.tu = t;
    if (!(M.rhead = (OLink*)malloc((m + 1) * sizeof(OLink))) || !(M.chead = (OLink*)malloc((n + 1) * sizeof(OLink))))
    {
        printf("初始化矩阵失败");
        exit(0);
    }
    for (i = 1; i <= m; i++)
    {
        M.rhead[i] = NULL;
    }
    for (j = 1; j <= n; j++)
    {
        M.chead[j] = NULL;
    }
    for (scanf("%d%d%d", &i, &j, &e); 0 != i; scanf("%d%d%d", &i, &j, &e)) {
        if (!(p = (OLNode*)malloc(sizeof(OLNode))))
        {
            printf("初始化三元组失败");
            exit(0);
        }
        p->i = i;
        p->j = j;
        p->e = e;
        //链接到行的指定位置
/*** 请在下方填写你的代码 *********/
/************* begin **************/


		if (M.rhead[i] == NULL || M.rhead[i]->j > j)
		{
			p->right = M.rhead[i];
			M.rhead[i] = p;
		}
		else 
		{
			for (q = M.rhead[i]; q->right&&q->right->j < j; q = q->right);
			p->right = q->right; 
			q->right = p;
		}
		if (M.chead[j] == NULL || M.chead[j]->i > i)
		{
			p->down = M.chead[j];
			M.chead[j] = p;
		}
		else
		{
			for (q = M.chead[j]; q->down&&q->down->i < i; q = q->down);
			p->down = q->down;
			q->down = p;
        }





/************** end ***************/
        //链接到列的指定位置

    }
    return M;
}
void display(CrossList M) {
    for (int i = 1; i <= M.nu; i++)
    {
        if (NULL != M.chead[i])
        {
            OLink p = M.chead[i];
            while (NULL != p)
            {
                printf("%d\t%d\t%d\n", p->i, p->j, p->e);
                p = p->down;
            }
        }
    }
}

数据结构与算法 - 图

第3关 实现图的深度优先遍历

#include "graph.h"
#include <stdio.h>
#include <stdlib.h>
void CreateAdj(AdjGraph *&G,int A[MAXV][MAXV],int n,int e)  //创建图的邻接表
{
    int i,j;
    ArcNode *p;
    G=(AdjGraph *)malloc(sizeof(AdjGraph));
    for(i=0;i<n;i++)                                        //给邻接表的头元素的指针域置初值
    {
        G->adjlist[i].firstarc=NULL;
    }
    for(i=0;i<n;i++)                                        //检查邻接表的每个元素
    {
        for(j=n-1;j>=0;j--)
        {
            if(A[i][j]!=0&&A[i][j]!=INF)                    //存在一条边
            {
                p=(ArcNode *)malloc(sizeof(ArcNode));       //创建一个结点p
                p->adjvex=j;                                //存放邻接点
                p->weight=A[i][j];                          //存放权
                p->nextarc=G->adjlist[i].firstarc;          //采用头插法插入结点p
                G->adjlist[i].firstarc=p;
            }
        }
    }
    G->n=n;
    G->e=e;
}
void DispAdj(AdjGraph *G)
{
    int i;
    ArcNode *p;
    for(i=0;i<G->n;i++)
    {
        p=G->adjlist[i].firstarc;
        printf("%3d: ",i);
        while(p!=NULL)
        {
            printf("%d[%d]→",p->adjvex,p->weight);
            p=p->nextarc;
        }
        printf("^\n");
    }
}
void DestroyAdj(AdjGraph *&G)
{
    int i;
    ArcNode *pre,*p;
    for(i=0;i<G->n;i++)                 //扫描所有单链表
    {
        pre=G->adjlist[i].firstarc;     //p指向第i个单链表的头结点
        if(pre!=NULL)
        {
            p=pre->nextarc;
            while(p!=NULL)              //释放第i个单链表的所有结点
            {
                free(pre);
                pre=p;
                p=p->nextarc;
            }
            free(pre);
        }
    }
    free(G);
}
//深度优先遍历
int visited[MAXV];                //全局数组,记录访问的点
void DFS(AdjGraph *G,int v)
{
    /********** Begin **********/
    visited[v] = 1;
    printf("%2d ", v); 

    ArcNode *p = G->adjlist[v].firstarc;
    while (p != NULL)
    {
        int w = p->adjvex; 
        if (!visited[w])
        {
            DFS(G, w); 
        }
        p = p->nextarc;
    }    
    /********** End **********/
}

第4关 实现图的广度优先遍历

 #include "graph.h"
#include <stdio.h>
#include <stdlib.h>
void CreateAdj(AdjGraph *&G,int A[MAXV][MAXV],int n,int e)  //创建图的邻接表
{
    int i,j;
    ArcNode *p;
    G=(AdjGraph *)malloc(sizeof(AdjGraph));
    for(i=0;i<n;i++)                                        //给邻接表的头元素的指针域置初值
    {
        G->adjlist[i].firstarc=NULL;
    }
    for(i=0;i<n;i++)                                        //检查邻接表的每个元素
    {
        for(j=n-1;j>=0;j--)
        {
            if(A[i][j]!=0&&A[i][j]!=INF)                    //存在一条边
            {
                p=(ArcNode *)malloc(sizeof(ArcNode));       //创建一个结点p
                p->adjvex=j;                                //存放邻接点
                p->weight=A[i][j];                          //存放权
                p->nextarc=G->adjlist[i].firstarc;          //采用头插法插入结点p
                G->adjlist[i].firstarc=p;
            }
        }
    }
    G->n=n;
    G->e=e;
}
void DispAdj(AdjGraph *G)
{
    int i;
    ArcNode *p;
    for(i=0;i<G->n;i++)
    {
        p=G->adjlist[i].firstarc;
        printf("%3d: ",i);
        while(p!=NULL)
        {
            printf("%d[%d]→",p->adjvex,p->weight);
            p=p->nextarc;
        }
        printf("^\n");
    }
}
void DestroyAdj(AdjGraph *&G)
{
    int i;
    ArcNode *pre,*p;
    for(i=0;i<G->n;i++)                 //扫描所有单链表
    {
        pre=G->adjlist[i].firstarc;     //p指向第i个单链表的头结点
        if(pre!=NULL)
        {
            p=pre->nextarc;
            while(p!=NULL)              //释放第i个单链表的所有结点
            {
                free(pre);
                pre=p;
                p=p->nextarc;
            }
            free(pre);
        }
    }
    free(G);
}
typedef struct
{
    int data[MAXV];
    int front, rear;
} Queue;

void InitQueue(Queue *Q)
{
    Q->front = Q->rear = -1;
}

int IsEmpty(Queue *Q)
{
    return Q->front == -1;
}

void Enqueue(Queue *Q, int value)
{
    if (Q->rear == MAXV - 1)
    {
        printf("Queue is full\n");
        exit(EXIT_FAILURE);
    }
    if (Q->front == -1)
    {
        Q->front = 0;
    }
    Q->rear++;
    Q->data[Q->rear] = value;
}

int Dequeue(Queue *Q)
{
    if (IsEmpty(Q))
    {
        printf("Queue is empty\n");
        exit(EXIT_FAILURE);
    }
    int value = Q->data[Q->front];
    if (Q->front == Q->rear)
    {
        Q->front = Q->rear = -1;
    }
    else
    {
        Q->front++;
    }
    return value;
}

// 广度优先遍历
void BFS(AdjGraph *G, int v)
{
    Queue Q;
    InitQueue(&Q);
    int visited[MAXV] = {0}; // Array to keep track of visited vertices

    visited[v] = 1;
    printf("%d ", v);
    Enqueue(&Q, v);

    while (!IsEmpty(&Q))
    {
        int currentVertex = Dequeue(&Q);

        ArcNode *p = G->adjlist[currentVertex].firstarc;
        while (p != NULL)
        {
            int adjVertex = p->adjvex;
            if (!visited[adjVertex])
            {
                visited[adjVertex] = 1;
                printf("%d ", adjVertex);
                Enqueue(&Q, adjVertex);
            }
            p = p->nextarc;
        }
    }
}

第5关 图的连通性问题

#include "graph.h"
#include <stdio.h>
#include <stdlib.h>
//prim
void Prim(MGraph g, int v) {
    int lowcost[MAXV];
    int closest[MAXV];
    int min, k, i, j;

    for (i = 0; i < g.n; i++) {
        lowcost[i] = g.edges[v][i];
        closest[i] = v;
    }

    lowcost[v] = 0;
    for (i = 1; i < g.n; i++) {
        min = INF;

        for (j = 0; j < g.n; j++) {
            if (lowcost[j] != 0 && lowcost[j] < min) {
                min = lowcost[j];
                k = j;
            }
        }

        printf("(%d,%d):%d\n", closest[k], k, min);
        lowcost[k] = 0;

        for (j = 0; j < g.n; j++) {
            if (g.edges[k][j] < lowcost[j]) {
                lowcost[j] = g.edges[k][j];
                closest[j] = k;
            }
        }
    }
}

//krusal
void InsertSort(Edge E[], int n) /*对E[0..n-1]按递增有序进行直接插入排序*/
{
    int i, j;
    Edge temp;
    for (i = 1; i < n; i++) {
        temp = E[i];
        j = i - 1;                /*从右向左在有序区E[0..i-1]中找E[i]的插入位置*/
        while (j >= 0 && temp.w < E[j].w) {
            E[j + 1] = E[j];    /*将关键字大于E[i].w的记录后移*/
            j--;
        }
        E[j + 1] = temp;        /*在j+1处插入E[i] */
    }
}

void Kruskal(MGraph g) {
    /********** Begin **********/

    Edge edges[MAXV * MAXV]; // 边集数组,存储所有边的信息
    int i, j, k = 0;
    for (i = 0; i < g.n; i++) {
        for (j = i + 1; j < g.n; j++) {
            if (g.edges[i][j] != 0 && g.edges[i][j] != INF) {
                edges[k].u = i;
                edges[k].v = j;
                edges[k].w = g.edges[i][j];
                k++;
            }
        }
    }
    InsertSort(edges, k); // 对边集数组进行排序

    int parent[MAXV]; // 存放顶点的祖先结点
    for (i = 0; i < g.n; i++) {
        parent[i] = -1; // 初始化为-1,表示每个顶点的祖先是自己
    }

    for (i = 0; i < k; i++) {
        int u = edges[i].u;
        int v = edges[i].v;
        int pu = u, pv = v;
        while (parent[pu] != -1) {
            pu = parent[pu]; // 找到u的祖先结点
        }
        while (parent[pv] != -1) {
            pv = parent[pv]; // 找到v的祖先结点
        }
        if (pu != pv) { // 如果u、v不在同一连通分量中,即不构成回路
            printf("(%d,%d):%d\n", u, v, edges[i].w);
            parent[pv] = pu; // 将v的祖先设置为u,合并连通分量
        }
    }

    /********** End **********/
}

第6关 有向无环图及其应用

#include "graph.h"
#include <stdio.h>
#include <stdlib.h>
void MatToList(MGraph g,ALGraph *&G)
/*将邻接矩阵g转换成邻接表G*/
{
    int i,j,n=g.n;                        /*n为顶点数*/
    ArcNode *p;
    G=(ALGraph *)malloc(sizeof(ALGraph));
    for (i=0;i<n;i++)                    /*给邻接表中所有头结点的指针域置初值*/
        G->adjlist[i].firstarc=NULL;
    for (i=0;i<n;i++)                    /*检查邻接矩阵中每个元素*/
        for (j=n-1;j>=0;j--)
            if (g.edges[i][j]!=0)                /*邻接矩阵的当前元素不为0*/
            {
                   p=(ArcNode *)malloc(sizeof(ArcNode));    /*创建一个结点*p*/
                p->adjvex=j;
                p->info=g.edges[i][j];
                p->nextarc=G->adjlist[i].firstarc;        /*将*p链到链表后*/
                G->adjlist[i].firstarc=p;
            }
    G->n=n;G->e=g.e;
}
void ListToMat(ALGraph *G,MGraph &g)
/*将邻接表G转换成邻接矩阵g*/
{
    int i,n=G->n;
    ArcNode *p;
    for (i=0;i<n;i++)
    {
        p=G->adjlist[i].firstarc;
        while (p!=NULL)
        {
            g.edges[i][p->adjvex]=p->info;
            p=p->nextarc;
        }
    }
    g.n=n;g.e=G->e;
}
void DispMat(MGraph g)
/*输出邻接矩阵g*/
{
    int i,j;
    for (i=0;i<g.n;i++)
    {
        for (j=0;j<g.n;j++)
            if (g.edges[i][j]==INF)
                printf("%3s","∞");
            else
                printf("%3d",g.edges[i][j]);
        printf("\n");
    }
}
//拓扑排序
void TopSort(ALGraph *G)
{
    
    int i,j;
    int St[MAXV],top=-1;              /*栈St的指针为top*/
    ArcNode *p;
    for (i=0;i<G->n;i++)            /*入度置初值0*/
        G->adjlist[i].count=0;
    for (i=0;i<G->n;i++)            /*求所有顶点的入度*/
    {
        p=G->adjlist[i].firstarc;
        while (p!=NULL)
        {
            G->adjlist[p->adjvex].count++;
            p=p->nextarc;
        }
    }
    for (i=0;i<G->n;i++)
        if (G->adjlist[i].count==0)  /*入度为0的顶点进栈*/
        {
            top++;
            St[top]=i;
        }
    while (top>-1)                     /*栈不为空时循环*/
    {
        /********** Begin **********/
        i = St[top];        // 出栈
        top--;
        printf("%d ", i);   // 输出顶点
        p = G->adjlist[i].firstarc;
        while (p != NULL) { // 对i号顶点的每个邻接点的入度减1
            j = p->adjvex;
            G->adjlist[j].count--;
            if (G->adjlist[j].count == 0) { // 若减到0则入栈
                top++;
                St[top] = j;
            }
            p = p->nextarc;
        }        
        /********** End **********/
    }
}

第7关 最短路径

 #include "graph.h"
#include <stdio.h>
#include <stdlib.h>
void Ppath(int path[][MAXV],int i,int j)  /*前向递归查找路径上的顶点*/
{
    int k;
    k=path[i][j];
    if (k==-1) return;    /*找到了起点则返回*/
    Ppath(path,i,k);    /*找顶点i的前一个顶点k*/
    printf("%d,",k);
    Ppath(path,k,j);    /*找顶点k的前一个顶点j*/
}
void Dispath(int A[][MAXV],int path[][MAXV],int n)
{
    int i,j;
    for (i=0;i<n;i++)
        for (j=0;j<n;j++)
        {
            if (A[i][j]==INF)
            {
                if (i!=j)
                    printf("从%d到%d没有路径\n",i,j);
            }
            else
            {
                printf("  从%d到%d=>路径长度:%d 路径:",i,j,A[i][j]);
                printf("%d,",i);    /*输出路径上的起点*/
                Ppath(path,i,j);    /*输出路径上的中间点*/
                printf("%d\n",j);    /*输出路径上的终点*/
            }
        }
}
void Floyd(MGraph g)
{
    /********** Begin **********/
    int A[MAXV][MAXV], path[MAXV][MAXV];
    int i, j, k, n = g.n;
    for (i = 0; i < n; i++)   
        for (j = 0; j < n; j++) {
            A[i][j] = g.edges[i][j];
            path[i][j] = -1;
        }
    for (k = 0; k < n; k++) {  
        for (i = 0; i < n; i++) {
            for (j = 0; j < n; j++) {
                if (A[i][j] > (A[i][k] + A[k][j])) {
                    A[i][j] = A[i][k] + A[k][j];
                    path[i][j] = k;
                }
            }
        }
    }   	
    /********** End **********/
    Dispath(A,path,g.n);   /*输出最短路径*/
}


数据结构与算法 - 树

第3关 打印二叉树

#include "tree.h"
#include <stdio.h>
#include <stdlib.h>
//创建二叉树
void CreateBTree(BTNode *&b,char *str)
{
    BTNode *St[MaxSize],*p;//St数组作为顺序栈
    int top=-1,k,j=0;//top作为栈顶指针
    char ch;
    b=NULL;//初始时二叉链为空
    ch=str[j];
    while(ch!='\0')
    {
        switch (ch)
        {
            case '(':top++;St[top]=p;k=1;break; //处理左孩子
            case ')':top--;break;               //栈顶的子树处理完毕
            case ',':k=2;break;                 //开始处理右孩子
            default:
                p=(BTNode*)malloc(sizeof(BTNode));  //创建一个结点由p指向它
                p->data=ch;                         //存放结点值
                p->lchild=p->rchild=NULL;           //左右指针都置为空
                if(b==NULL)                         //若尚未建立根结点
                {
                    b=p;                            //b所指结点作为根结点
                }
                else                                //已建立二叉树根结点
                {
                    switch(k)
                    {
                        case 1:St[top]->lchild=p;break;     //新建结点作为栈顶左孩子
                        case 2:St[top]->rchild=p;break;     //新建结点作为栈顶右孩子
                    }
                }
        }
        j++;                                                //继续扫描str
        ch=str[j];
    }
    
}
//销毁树
void DestroyBTree(BTNode *&b)
{
    if(b!=NULL)
    {
        DestroyBTree(b->lchild);
        DestroyBTree(b->rchild);
        free(b);
    }
}
//输出树

void DispBTree(BTNode *b)
{
    /********** Begin **********/
    printf("%c",b->data);
    if(b->lchild==NULL&&b->rchild==NULL){
        return;
    }
    printf("(");
    if(b->lchild){
        DispBTree(b->lchild);
    }
    if(b->rchild){
        printf(",");
        DispBTree(b->rchild);
    }
    printf(")");
    /********** End **********/    
}

第4关 遍历二叉树

#include "tree.h"
#include <stdio.h>
#include <stdlib.h>
//先序遍历
void PreOrder(BTNode *b)
{
    /********** Begin **********/
    printf("%c",b->data);
    if(b->lchild){
        PreOrder(b->lchild);
    }
    if(b->rchild){
        PreOrder(b->rchild);
    }
    /********** End**********/
}
//中序遍历
void InOrder(BTNode *b)
{
    /********** Begin **********/
    if(b->lchild){
        InOrder(b->lchild);
    }
    printf("%c",b->data);
    if(b->rchild){
        InOrder(b->rchild);
    }
    
    /********** End **********/
}
//后续遍历
void PostOrder(BTNode *b)
{
    /********** Begin **********/
    if(b->lchild){
        PostOrder(b->lchild);
    }
    if(b->rchild){
        PostOrder(b->rchild);
    }
    printf("%c",b->data);
    
    /********** End **********/
}

第5关 由双遍历序列构造二叉树

#include "tree.h"
#include <stdio.h>
#include <stdlib.h>
//由先序序列和中序序列构造二叉树
BTNode *CreateBT1(char *pre, char *in, int n)
{
    if (n <= 0)
        return NULL;

    BTNode *root = (BTNode *)malloc(sizeof(BTNode));
    root->data = pre[0];

    int rootIndex = 0;
    while (in[rootIndex] != pre[0])
        rootIndex++;

    root->lchild = CreateBT1(pre + 1, in, rootIndex);
    root->rchild = CreateBT1(pre + 1 + rootIndex, in + rootIndex + 1, n - 1 - rootIndex);

    return root;
}

// 由中序序列和后序序列构造二叉树
BTNode *CreateBT2(char *post, char *in, int n)
{
    if (n <= 0)
        return NULL;

    BTNode *root = (BTNode *)malloc(sizeof(BTNode));
    root->data = post[n - 1];

    int rootIndex = 0;
    while (in[rootIndex] != post[n - 1])
        rootIndex++;

    root->lchild = CreateBT2(post, in, rootIndex);
    root->rchild = CreateBT2(post + rootIndex, in + rootIndex + 1, n - 1 - rootIndex);

    return root;
}

第6关 线索二叉树

 #include <stdio.h>
#include <stdlib.h>
#include "tree.h"
TBTNode *pre;                   //全局变量
//对二叉排序树进行线索化
void Thread(TBTNode *&p)
{
    if(p!=NULL)
    {
        Thread(p->lchild);      //左孩子线索化
        if(p->lchild==NULL)     //左孩子不存在,进行前驱结点线索化
        {
            p->lchild=pre;      //建立当前结点的前驱结点线索
            p->ltag=1;
        }
        else
        {
            p->ltag=0;          //p结点的左子树已线索化
        }
        if(pre->rchild==NULL)   //对pre的后继结点线索化
        {
            pre->rchild=p;      //建立前驱结点的后继结点线索
            pre->rtag=1;
        }
        else
        {
            pre->rtag=0;
        }
        pre=p;
        Thread(p->rchild);      //右子树线索化
    }
}
//中序线索化二叉树
TBTNode *CreateThread(TBTNode *b)
{
    /********** Begin **********/
 	TBTNode *root;
	root=(TBTNode *)malloc(sizeof(TBTNode));
	root->ltag=0;root->rtag=1;
	root->rchild=b;
	if(b==NULL)
		root->lchild=root;
	else
	{
		root->lchild=b;
		pre=root;
		Thread(b);
		pre->rchild=root;
		pre->rtag=1;
		root->rchild=pre;
	}   
    /********** End **********/
}
//遍历线索化二叉树
void ThInOrder(TBTNode *tb)
{
    TBTNode *p=tb->lchild;                      //p指向根结点
    while(p!=tb)
    {
        while(p->ltag==0)p=p->lchild;           //找开始结点
        printf("%c",p->data);                   //访问开始结点
        while(p->rtag==1&&p->rchild!=tb)
        {
            p=p->rchild;
            printf("%c",p->data);
        }
        p=p->rchild;
    }
}

第8关 树与等价问题

#include <stdio.h>
#include "tree.h"
//初始化并查集树
void MAKE_SET(UFSTree t[])
{
    int i;
    for (i=1;i<=N;i++)
    {
        t[i].data=i;                      //数据为该人的编号
        t[i].rank=0;                      //秩初始化为0
        t[i].parent=i;                    //双亲初始化指向自已
    }
}
//在x所在子树中查找集合编号
int FIND_SET(UFSTree t[],int x)
{
    if (x!=t[x].parent)                   //双亲不是自已
        return(FIND_SET(t,t[x].parent));  //递归在双亲中找x
    else
        return(x);                        //双亲是自已,返回x
}
//将x和y所在的子树合并
void UNION(UFSTree t[],int x,int y)
{
    /********** Begin **********/
    int tx=FIND_SET(t,x);
    int ty=FIND_SET(t,y);
    if(tx==ty){
        return;
    }else{
        t[ty].parent=tx;
    }   
    /********** End **********/
}


第9关 最优二叉树(哈夫曼树)

#include <stdio.h>
#include "tree.h"
#include <string.h>
void CreateHT(HTNode ht[],int n)
{
    int i,k,lnode,rnode;
    double min1,min2;
    for (i=0;i<2*n-1;i++)            /*所有结点的相关域置初值-1*/
        ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
    for (i=n;i<2*n-1;i++)            /*构造哈夫曼树*/
    {
        /********** Begin **********/
        min1=min2=32767;
        lnode=rnode=-1;
        for(k=0;k<=i-1;k++)
        {
            if(ht[k].parent==-1)
            {
                if(ht[k].weight<min1)
                {
                    min2=min1;
                    rnode=lnode;
                    min1=ht[k].weight;
                    lnode=k;
                }
                else if (ht[k].weight<min2)
                {
                    min2=ht[k].weight;
                    rnode=k;
                }
            }
        }
        ht[i].weight=ht[lnode].weight + ht[rnode].weight;
        ht[i].lchild=lnode;
        ht[i].rchild=rnode;
        ht[lnode].parent=i;  
        ht[rnode].parent=i;       
        /********** End **********/
    }
}
void CreateHCode(HTNode ht[],HCode hcd[],int n)
{
    int i,f,c;
    HCode hc;
    for (i=0;i<n;i++)    /*根据哈夫曼树求哈夫曼编码*/
    {
        hc.start=n;c=i;
        f=ht[i].parent;
        while (f!=-1)    /*循序直到树根结点*/
        {
            /********** Begin **********/

            if(ht[f].lchild==c)
				hc.cd[hc.start--]='0';
			else
				hc.cd[hc.start--]='1';
			c=f;
			f=ht[f].parent;             
            /********** End **********/
        }
        hc.start++;        /*start指向哈夫曼编码最开始字符*/
        hcd[i]=hc;
    }
}
void DispHCode(HTNode ht[],HCode hcd[],int n)
{
    int i,k;
    double sum=0,m=0;
    int j;
    for (i=0;i<n;i++)
    {
        j=0;
        printf("%s:\t",ht[i].data);
        for (k=hcd[i].start;k<=n;k++)
        {
            printf("%c",hcd[i].cd[k]);
            j++;
        }
        m+=ht[i].weight;
        sum+=ht[i].weight*j;
        printf("\n");
    }
    printf("平均长度=%g\n",1.0*sum/m);
}

第10关 回溯法与树的遍历

#include <stdio.h>
#include <stdlib.h>
#include "queens.h"
#define MAXN 20              //最多皇后个数
int q[MAXN];                 //存放各皇后所在列号
int count = 0;              //输出一个解
void dispsolution(int n)     
{
    printf("第%d个解:", ++count);
    for (int i = 1; i <= n; i++) {
        printf("(%d,%d)", i, q[i]);
    }
    printf("\n");
}

bool place(int i)             
{
    int j = 1;
    if (i == 1)return true;
    while (j < i)                  
    {
        if ((q[j] == q[i]) || (abs(q[j] - q[i]) == abs(j - i))) {
            return false;
        }
        j++;
    }
    return true;
}

void Queens(int n)                  
{
    int i = 1;                        
    q[i] = 0;                         
    while (i >= 1)                     
    {
        /********** Begin **********/
        q[i]++;
        while (q[i] <= n) {
            if (place(i)) {
                if (i == n) {
                    dispsolution(n);  
                    q[i]++;
                } else {
                    i++;
                    q[i] = 0; 
                    break;
                }
            } else {
                q[i]++;
            }
        }
        if (q[i] > n) {
            i--; // 回溯
        }

        /********** End **********/
    }
}

第11关 树的计数

#include <stdio.h>
/********** Begin **********/
struct Catalan{
    int c=1;
    int C(int x, int y){
        int m;
        if( x < 0 || y < 0 || y > x ){
            m = 0;
        }
        else if( y == 0 ){
            m = 1;
        }
        else if( y > x / 2 ){
            y = x - y;
            m = C( x , y );
        }
        else{
            m = C( x - 1, y - 1)*x / y;
        }
        return m;
    };

    int query(int n){
        for(int i=1;i<=n;i++){
            c=c*(4*i-2)/(i+1);
        }
        return c;
    } 
};
int main(){
    Catalan ca;
    int n;
    scanf("%d",&n);
    printf("%d",ca.query(n));
}
/********** End **********/

顺序表的查找

第1关 顺序表的查找

#include<stdio.h>


int binarySearch(int array[], int len, int target) {
	
	/********* Begin *********/
    int left = 0;
    int right = len-1;

    while (left <= right) {
        int mid = left + (right - left) / 2;

        if (array[mid] == target) {
            return mid; 
        } else if (array[mid] < target) {
            right = mid - 1; 
        } else {
            left = mid + 1; 
        }
    }

    return -1; 
	/********* End *********/
}

int main(){	
	int target, len;
    scanf("%d", &target);  //输入整数并赋值给变量a
    scanf("%d", &len);  //输入整数并赋值给变量b
    int a[10];
	int i = 0;
	for (;i < len;i++) {
		scanf("%d", &a[i]);
	}
	printf("%d\n", binarySearch(a, len, target));
	return 0;
}

二叉排序树和二叉平衡树

第1关 二叉排序树的定义、查找和构造

#include <stdio.h>
#include <math.h>
#include <stdlib.h>


//二叉树的定义
typedef struct BinaryNode {
	int data;//数据
	int index;//在数组中的位置
	struct BinaryNode* leftChild, * rightChild;//左子树和右子树
}BinaryNode, * BinaryTree;

//创建二叉排序树
//tree:待构造的二叉树
//array:顺序表
//start:本次操作创建的子树在顺序表中的起始索引
//end:本次操作创建的子树在顺序表中的结束索引
void createBinarySortTree(BinaryTree tree, int array[], int start, int end) {
	/********* Begin *********/
	//从start到end中随机找一个数字作为根节点的索引  
    int rootIndex = start == end ? start : (rand() % (end - start) + start);  
    //对树根赋值  
    tree->data = array[rootIndex]; 
	/********* End *********/
	tree->index = rootIndex;
	//当左子树中元素个数大于1
	if (start < rootIndex) {
		//给左子树分配空间
		tree->leftChild = (BinaryTree)malloc(sizeof(BinaryNode));
		//递归调用,生成左子树
		createBinarySortTree(tree->leftChild, array, start, rootIndex - 1);
	}
	else {
		//左子树中已经没有元素
		tree->leftChild = NULL;
	}
	//当右子树中元素个数大于1
	if (rootIndex  < end) {
		//给右子树分配空间
		tree->rightChild = (BinaryTree)malloc(sizeof(BinaryNode));
		//递归调用,生成右子树
		createBinarySortTree(tree->rightChild, array,  rootIndex + 1, end);
	}
	else {
		//右子树中已经没有元素
		tree->rightChild = NULL;
	}
	return;
}



//主函数
int main() {
	//顺序表
	int array[6];
	for (int i = 0; i < 6; i++) {
		scanf("%d", &array[i]);
	}
	//顺序表构造的次优静态查找树
	BinaryTree tree = (BinaryTree)malloc(sizeof(BinaryNode));
	//构造次优静态查找树
	createBinarySortTree(tree, array,  0, 5);
	printf("%d\n", tree->rightChild->rightChild->data);
	return 0;
}

第2关 二叉排序树的插入

#include <stdio.h>
#include <math.h>
#include <stdlib.h>


//二叉树的定义
typedef struct BinaryNode {
	int data;//数据
	int index;//在数组中的位置
	struct BinaryNode* leftChild, * rightChild;//左子树和右子树
}BinaryNode, * BinaryTree;

//初始化二叉树
void initBinaryTree(BinaryTree tree) {
	tree->data = -1;
	tree->index = -1;
	tree->leftChild = NULL;
	tree->rightChild = NULL;
}

//创建二叉排序树
//tree:待构造的二叉树
//target:待插入的元素
//index:待插入元素在数组中的索引
int binaryTreeInsert(BinaryTree tree, int target, int index) {	
	if (tree->data == -1) {
		tree->data = target;
		tree->index = index;
		return -1;
	}
	else {
		if (target > tree->data) {
			//待插入元素大于当前子树的根节点,进入右子树
			if (tree->rightChild == NULL) {
				//如果右子树不存在,构建右子树
				tree->rightChild = (BinaryTree)malloc(sizeof(BinaryNode));
				//初始化右子树
				initBinaryTree(tree->rightChild);
			}
			//递归插入右子树中
			return binaryTreeInsert(tree->rightChild, target, index);
		}
		else if (target < tree->data ){
			/********* Begin *********/			
            if (tree->leftChild == NULL) {
                //如果左子树不存在,构建左子树
                tree->leftChild = (BinaryTree)malloc(sizeof(BinaryNode));
                //初始化左子树
                initBinaryTree(tree->leftChild);
            }
            //递归插入左子树中
            binaryTreeInsert(tree->leftChild, target,index);		

			/********* End *********/
		}
		else {
			/********* Begin *********/
			return tree->index;			
			/********* End *********/
		}
	}
}

//主函数
int main() {
	int array[7];
	for (int i = 0; i < 7; i++) {
		scanf("%d", &array[i]);
	}
	BinaryTree tree = (BinaryTree)malloc(sizeof(BinaryNode));;
	initBinaryTree(tree);
	for (int i = 0; i < 7; i++) {
		printf("%d\n", binaryTreeInsert(tree, array[i], i));
	}
	return 0;
}


第3关 二叉排序树的删除

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

//二叉树的定义
typedef struct BinaryNode {
	int data;//数据
	int index;//在数组中的位置
	struct BinaryNode* leftChild, * rightChild;//左子树和右子树
}BinaryNode, * BinaryTree;

//初始化二叉树
void initTree(BinaryTree tree, int data) {
	tree->data = data;
	tree->leftChild = NULL;
	tree->rightChild = NULL;
}

//查找指定节点的前驱节点以及前驱节点的父节点
//tree:待查找的节点
//preParentNode:待查找的节点的前驱节点的父节点
//返回待查找的节点的前驱节点
BinaryTree searchPreNode(BinaryTree tree, BinaryTree *preParentNode) {
	//初始的时候,父节点就是待查找的节点
	*preParentNode = tree;
	//进入左子树
	BinaryTree preNode = tree->leftChild;
	//循环遍历右子树,直到走到空节点
	while (preNode->rightChild != NULL) {
		//在进入右子树之前,记录下父节点
		*preParentNode = preNode;
		//进入右子树
		preNode = preNode->rightChild;
	}
	return preNode;
}

//根据值找节点
//tree:查找树
//target:目标节点的值
//parentNode:目标节点的父节点
//返回目标节点
BinaryTree searchNode(BinaryTree tree, int target, BinaryTree *parentNode) {
	if (tree->data == target) {
		return tree;
	}
	//目标值大于根节点的值,进入右子树
	else if (tree->data < target) {
		*parentNode = tree;
		//递归查找
		return searchNode(tree->rightChild, target, parentNode);
	}
	//目标值大于根节点的值,进入左子树
	else {
		*parentNode = tree;
		//递归查找
		return searchNode(tree->leftChild, target, parentNode);
	}
}

//删除左右子树都为空的节点
void deleteBothEmpty(BinaryTree parentNode, int target) {
	//如果节点是父节点的左子树的根,则将父节点的左子树清空
	if (parentNode->leftChild != NULL && parentNode->leftChild->data == target) {
		parentNode->leftChild = NULL;
	}
	//如果节点是父节点的右子树的根,则将父节点的右子树清空
	else {
		parentNode->rightChild = NULL;
	}
}

//删除左右子树只有一个为空的节点
void deleteOneEmpty(BinaryTree targetNode, BinaryTree parentNode, int target) {
	//被删除节点是父节点的左子树
	if (parentNode->leftChild != NULL && parentNode->leftChild->data == target) {
		//将被删除节点的左子树挂到父节点的左子树上
		if (targetNode->leftChild != NULL) {
			parentNode->leftChild = targetNode->leftChild;
		}
		//将被删除节点的右子树挂到父节点的左子树上
		else {
			parentNode->leftChild = targetNode->rightChild;
		}
	}
	//被删除节点是父节点的右子树
	else {
		//将被删除节点的左子树挂到父节点的右子树上
		if (targetNode->leftChild != NULL) {
			parentNode->rightChild = targetNode->leftChild;
		}
		//将被删除节点的右子树挂到父节点的右子树上
		else {
			parentNode->rightChild = targetNode->rightChild;
		}
	}
}

//删除左右子树都不为空的节点
void deleteNotEmpty(BinaryTree targetNode, BinaryTree parentNode, int target) {
	//前驱节点的父节点的初始值
	BinaryTree preParentNode = targetNode;
	//找到前驱节点以及前驱节点的父节点
	BinaryTree preNode = searchPreNode(targetNode, &preParentNode);
	//先删除前驱节点和整棵树的连接
	deleteOneEmpty(preNode, preParentNode, preNode->data);
	//然后用前驱节点替代当前节点
	//替代的第一步是更换父节点的指针
	//替代的第二步是将子节点挂到前驱节点上
	//代码未给出,作为练习
	/********* Begin *********/
	targetNode->data = preNode->data;

	/********* End *********/
}

	

void binaryTreeDelete(BinaryTree tree, int target) {
	//待删除元素的父节点
	BinaryTree parentNode = tree;
	//首先找到待删除的元素所在的节点以及父节点
	BinaryTree targetNode = searchNode(tree, target, &parentNode);
	if (targetNode->leftChild == NULL && targetNode->rightChild == NULL) {
		deleteBothEmpty(parentNode, target);
	}
	//如果这个节点没有左子树,或者没有右子树
	else if (targetNode->leftChild == NULL || targetNode->rightChild == NULL) {
		deleteOneEmpty(targetNode, parentNode, target);
	}
	else {
		deleteNotEmpty(targetNode, parentNode, target);
	}

}

void middleSearch(BinaryTree rootTree) {
	if (rootTree->leftChild != NULL) {
		middleSearch(rootTree->leftChild);
	}
	printf("%d ", rootTree->data);
	if (rootTree->rightChild != NULL) {
		middleSearch(rootTree->rightChild);
	}
}



//主函数
int main() {
	BinaryTree rootTree = (BinaryTree)malloc(sizeof(BinaryNode));
	initTree(rootTree, 100);
	BinaryTree rightRootTree = (BinaryTree)malloc(sizeof(BinaryNode));
	initTree(rightRootTree, 112);
	BinaryTree tree3 = (BinaryTree)malloc(sizeof(BinaryNode));
	initTree(tree3, 102);
	BinaryTree tree4 = (BinaryTree)malloc(sizeof(BinaryNode));
	initTree(tree4, 120);
	BinaryTree tree5 = (BinaryTree)malloc(sizeof(BinaryNode));
	initTree(tree5, 108);
	BinaryTree tree6 = (BinaryTree)malloc(sizeof(BinaryNode));
	initTree(tree6, 105);
	//构建二叉树
	rootTree->rightChild = rightRootTree;
	rightRootTree->leftChild = tree3;
	rightRootTree->rightChild = tree4;
	tree3->rightChild = tree5;
	tree5->leftChild = tree6;
	//删除节点
	int deleteNum;
	scanf("%d", &deleteNum);
	binaryTreeDelete(rootTree, deleteNum);
	middleSearch(rootTree);
	return 0;
}


第4关 平衡二叉树

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//二叉树的定义
typedef struct BinaryNode {
    int data;//数据
    int balance;//节点的平衡因子
    struct BinaryNode* leftChild, * rightChild;//左子树和右子树
}BinaryNode, * BinaryTree;

//左旋转
//对以p为根结点的树左旋,同时使得p指针指向新的根结点
void leftRotate(BinaryTree* p)
{
    //右节点,新的树根节点
    BinaryTree rightNode = (*p)->rightChild;
    //原来的根的右节点,是新根的左节点
    (*p)->rightChild = rightNode->leftChild;
    rightNode->leftChild = *p;
    *p = rightNode;
}

//右旋转
//对以p为根结点的树右旋,同时使得p指针指向新的根结点
void rightRotate(BinaryTree* p)
{
    /********* Begin *********/
    BinaryTree leftNode = (*p)->leftChild;
    //原来的根的右节点,是新根的左节点
    (*p)->leftChild = leftNode->rightChild;
    leftNode->rightChild = *p;
    *p = leftNode;

    /********* End *********/
}


//左子树比右子树的高度大2
void balanceLeftTree(BinaryTree* tree)
{
    //左子树,左子树的右子树
    BinaryTree leftNode, leftRightNode;
    //左子树赋值
    leftNode = (*tree)->leftChild; 
    //如果左子树的左子树比右子树高1,说明是新节点是插入在了左子树的左子树上
    if (leftNode->balance == 1) {       
        (*tree)->balance = leftNode->balance = 0;
        //对整个书右旋即可
        rightRotate(tree);
    }
    //如果左子树的左子树比右子树矮1,说明是新节点是插入在了左子树的右子树上
    if (leftNode->balance == -1) {
        leftRightNode = leftNode->rightChild;
        if (leftRightNode->balance == 1) {
            (*tree)->balance = -1;
            leftNode->balance = 0;
        }
        else if (leftRightNode->balance == -1) {
            (*tree)->balance = 0;
            leftNode->balance = 1;
        }
        else {
            (*tree)->balance = leftNode->balance = 0;
        }      
        leftRightNode->balance = 0;
        //对左子树进行左旋,并将tree调整为左旋完成后左子树的根节点
        leftRotate(&(*tree)->leftChild);
        //右旋
        rightRotate(tree);
    }  
    
}

//RR旋转
//右子树的平衡处理同左子树的平衡处理完全类似
void balanceRightTree(BinaryTree* tree)
{
    BinaryTree leftNode, leftLeftNode;
    leftNode = (*tree)->rightChild;
    if (leftNode->balance == -1) {
        (*tree)->balance = leftNode->balance = 0;
        leftRotate(tree);
    } 
    if (leftNode->balance == 1) {
        leftLeftNode = leftNode->leftChild;
        if (leftLeftNode->balance == 1) {
            (*tree)->balance = 0;
            leftNode->balance = -1;
        }
        else if (leftLeftNode->balance == 0) {
            (*tree)->balance = leftNode->balance = 0;
        }
        else {
            (*tree)->balance = 0;
            leftNode->balance = 1;
        }      
        leftLeftNode->balance = 0;
        rightRotate(&(*tree)->rightChild);
        leftRotate(tree);
    }
}

insertAVLTree(BinaryTree* tree, int data, int* isTaller)
{
    //如果是空树,则新建
    if ((*tree) == NULL)
    {
        //分配空间
        (*tree) = (BinaryTree)malloc(sizeof(BinaryNode));
        //初始化平衡因子为0
        (*tree)->balance = 0;
        //初始化数据
        (*tree)->data = data;
        (*tree)->leftChild = NULL;
        (*tree)->rightChild = NULL;
        //树的高度增加了
        *isTaller = 1;
    }
    //如果待插入的数据小于根节点的数据
    else if (data < (*tree)->data)
    {      
        //插入到左子树中
        insertAVLTree(&(*tree)->leftChild, data, isTaller);
        //如果插入使得左子树变高
        if (*isTaller)
        {
            //如果本来左子树就比右子树高1,则现在左子树比右子树高2
            if ((*tree)->balance == 1) {
                //需要对整个树进行平衡调整(左旋和先左旋再右旋)
                balanceLeftTree(tree);
                //树高度不变(平衡之前树的高度比原来大了1,平衡之后又恢复了)
                *isTaller = 0;
            }
            //如果本来左子树和右子树一样高,则现在左子树比右子树高1
            else if ((*tree)->balance == 0) {
                //平衡因子加1
                (*tree)->balance = 1;
                //树高度增加
                *isTaller = 1;
            }
            //如果本来左子树就比右子树矮1
            else {
                //平衡因子变为0
                (*tree)->balance = 0;
                //树高度不变
                *isTaller = 0;
            }
        }     
        
    }
    //和上面完全对称
    else
    {
        insertAVLTree(&(*tree)->rightChild, data, isTaller);
        if (*isTaller)
        {
            if ((*tree)->balance == 1) {
                (*tree)->balance = 0;
                *isTaller = 0;
            }
            else if ((*tree)->balance == 0) {
                (*tree)->balance = -1;
                *isTaller = 1;
            }
            else {
                balanceRightTree(tree);
                *isTaller = 0;
            }
        }              
    }
}

void middleSearch(BinaryTree rootTree) {
    if (rootTree->leftChild != NULL) {
        middleSearch(rootTree->leftChild);
    }
    printf("%d ", rootTree->data);
    if (rootTree->rightChild != NULL) {
        middleSearch(rootTree->rightChild);
    }
}

//求树高
int getTreeHeight(BinaryTree tree) {
    if (tree == NULL) {
        return 0;
    }
    else {
        int leftHeight = getTreeHeight(tree->leftChild);
        int rightHeight = getTreeHeight(tree->rightChild);
        int res =  1 + (leftHeight > rightHeight ? leftHeight : rightHeight);
        return res;
    }
}

//是否是AVL树
//0否1是
int isAVLTree(BinaryTree tree) {
    if (tree == NULL) {
        return 1;
    }
    int leftHeight = getTreeHeight(tree->leftChild);
    int rightHeight = getTreeHeight(tree->rightChild);
    if (1 >= abs(leftHeight - rightHeight) && isAVLTree(tree->leftChild) && isAVLTree(tree->rightChild)) {
        return 1;
    }
    return 0;
    
}

int main()
{
    //数组
    int array[6];
    for (int i = 0; i < 6; i++)
    {
        scanf("%d", &array[i]);
    }
    //树的根节点
    BinaryTree tree = NULL;
    //树在插入完成之后是否增高了,1是0否
    int isTaller;
    //构建AVL树
    for (int i = 0; i < 6; i++)
    {
        insertAVLTree(&tree, array[i], &isTaller);
    }
    printf("%d\n", isAVLTree(tree));
}

哈希表

第2关 哈希表的基本操作

 #include <stdio.h>
#include <stdlib.h>
#define HASHSIZE 7 //定义散列表长为数组的长度
#define NULLKEY -1
typedef struct{
    int *elem;//数据元素存储地址,动态分配数组
    int count; //当前数据元素个数
}HashTable;
//对哈希表进行初始化
void Init(HashTable *hashTable){
    int i;
    hashTable->elem= (int *)malloc(HASHSIZE*sizeof(int));
    hashTable->count=HASHSIZE;
    for (i=0;i<HASHSIZE;i++){
        hashTable->elem[i]=NULLKEY;
    }
}
//哈希函数(除留余数法)
int Hash(int data){
    return data%HASHSIZE;
}
//哈希表的插入函数,可用于构造哈希表
void Insert(HashTable *hashTable,int data){
    int hashAddress=Hash(data); //求哈希地址
    //发生冲突
    while(hashTable->elem[hashAddress]!=NULLKEY){
        //利用开放定址法解决冲突
        hashAddress=(++hashAddress)%HASHSIZE;
    }
    hashTable->elem[hashAddress]=data;
}
//哈希表的查找算法
int Search(HashTable *hashTable,int data){
/********* begin *************/

    int hashAddress=Hash(data); 
    while(hashTable->elem[hashAddress]!=data){
        hashAddress=(++hashAddress)%HASHSIZE;
        if (hashTable->elem[hashAddress]==NULLKEY||hashAddress==Hash(data)){
            return -1;
        }
    }
    return hashAddress;



/********* end ***************/
}
int main(){
    int i,result;
    HashTable hashTable;
    int arr[HASHSIZE]={13,29,27,28,26,30,38};
    //初始化哈希表
    Init(&hashTable);
    //利用插入函数构造哈希表
    for (i=0;i<HASHSIZE;i++){
        Insert(&hashTable,arr[i]);
    }
    //调用查找算法
    result= Search(&hashTable,29);
    if (result==-1) printf("查找失败");
    else printf("29在哈希表中的位置是:%d",result+1);
    return  0;
}

数据结构与算法 - 内部排序

第2关 插入排序

#include<stdio.h>
#include<stdlib.h>

void DirecInsSort(int* a, int n)
{
    int i, k;
    for (i=1; i<n; i++) {
        // 请在此添加代码,补全函数DirecInsSort
        /********** Begin *********/
        if(a[i]<a[i-1]){
            k=a[i];
			int j;
            for(j=i-1;j>=0&&a[j]>k;j--){
                a[j+1]=a[j];
            }
            a[j+1]=k;
        }


        /********** End **********/
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    int i;
    int * a=(int*)malloc(sizeof(int)*n);
    for (i=0; i<n; i++) scanf("%d", &a[i]);
    DirecInsSort(a,n);
    for (i=0; i<n; i++) printf("%d ", a[i]);
    return 0;
}

第3关 快速排序

#include<stdio.h>
#include<stdlib.h>

int Partition(int a[], int low, int high){
    int pivot = a[low];
    while(low<high){
        while(low<high&&a[high]>=pivot) high--;
        a[low] = a[high];
        while(low<high&&a[low]<=pivot) low++;
        a[high] = a[low];
    }
    a[low] = pivot;
    return low;
}

void QuickSort(int a[], int low, int high){
    if(low<high){
        int pivotpos = Partition(a,low,high);
        // 请在此添加代码,补全函数DirecInsSort
        /********** Begin *********/
        QuickSort(a,low,pivotpos);
        QuickSort(a,pivotpos+1,high);


        /********** End **********/
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    int i;
    int * a=(int*)malloc(sizeof(int)*n);
    for (i=0; i<n; i++) scanf("%d", &a[i]);
    QuickSort(a,0,n-1);
    for (i=0; i<n; i++) printf("%d ", a[i]);
    return 0;
}

第4关 选择排序

#include<stdio.h>
#include<stdlib.h>

void SimpSelSort(int a[], int n){
    // 请在此添加代码,补全函数SimpSelSort
    /********** Begin *********/
	for (int i = 0; i < n-1; i++) {
		int min = i;
		for (int j = i; j < n; j++) {
			if (a[min] > a[j]) {
				min = j;
			}
		}
		if (min != i) {
			int tmp=a[i];
			a[i]=a[min];
			a[min]=tmp;
		}
	}


    /********** End **********/
}

int main()
{
    int n;
    scanf("%d", &n);
    int i;
    int * a=(int*)malloc(sizeof(int)*n);
    for (i=0; i<n; i++) scanf("%d", &a[i]);
    SimpSelSort(a,n);
    for (i=0; i<n; i++) printf("%d ", a[i]);
    return 0;
}

第5关 归并排序

#include<stdio.h>
#include<stdlib.h>

void Merge(int a[], int low, int mid, int high)
{
    int * b=(int*)malloc(sizeof(int)*(high+1));
    int i,j,k;
    for(k=low; k<=high; k++) b[k] = a[k];
    for(i=low,j=mid+1,k=low; i<=mid&&j<=high; k++){
        if(b[i]<=b[j]) a[k] = b[i++];
        else a[k] = b[j++];
    }
    while(i<=mid) a[k++] = b[i++];
    while(j<=high) a[k++] = b[j++];
}

void MergeSort(int a[], int low, int high)
{
    if(low<high){
        // 请在此添加代码,补全函数MergeSort
        /********** Begin *********/
        int mid=(low+high)/2;
       	MergeSort(a,low,mid);
        MergeSort(a,mid+1,high);
        Merge(a,low,mid,high);
        /********** End **********/
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    int i;
    int * a=(int*)malloc(sizeof(int)*n);
    for (i=0; i<n; i++) scanf("%d", &a[i]);
    MergeSort(a, 0, n-1);
    for (i=0; i<n; i++) printf("%d ", a[i]);
    return 0;
}

第6关 基数排序

#include <stdio.h>
#include <stdlib.h>
#define RADIX 10 // 对整数,基数为10 
#define MAX_LENGTH 100 // 最大元素个数

// 静态链表结点 
struct node
{
    int data;
    int next;
}; 

// 获取关键字每一位数字
int get_digit(int n, int loc)
{
    int i;
    for(i=1; i<loc; i++) n = n/10;
    return n%10;
} 

// 分配和收集操作
void distri_collect(struct node r[], int length, int loc)
{
  
    int front[RADIX], rear[RADIX]; // 辅助数组,指向每个链队列 
    int i;
    for(i=0; i<RADIX; i++) // 初始为空
    {
        front[i] = 0;
        rear[i] = 0;
    }
        
    // 遍历整个静态链表,按照关键字分配到各链队列
    int p,digit;
    for(p = r[0].next ; p!=0 ; p=r[p].next)
    {
        digit = get_digit(r[p].data, loc);
        if(front[digit] == 0) front[digit] = p; // 链队列为空时直接插入
        else r[rear[digit]].next = p; // 插入尾部
        rear[digit] = p; 
    }
    
    // 收集合并
    for(i=0; front[i] == 0 && i<RADIX; i++);
    r[0].next = front[i];
    p = rear[i];
    while(i<RADIX)
    {
        for(i++;i<RADIX-1 && front[i]==0;++i);
        if(i>=RADIX) break; // 对最后一个元素特殊处理 
        if(front[i])  
        {
            // 链接两个非空链队列 
            r[p].next = front[i];
            p = rear[i]; 
        }
    } 
    r[p].next = 0;
}

void RadixSort(int a[], int length, int k)
{
    struct node r[MAX_LENGTH]; // 创建静态链表保存数据
    r[0].next = 0; // 初始化链表为空 
    int i;
    for(i=0; i<length; i++)
    {
        r[i].next = i+1;
        r[i+1].data = a[i];
    }
    r[i].next = 0; // 链表最后一个元素指向0,表示链表结束 
    // 请在此添加代码,补全函数RadixSort
    // 对关键字按照从低位到高位进行排序
    /********** Begin *********/
    for (int loc = 1; loc <= k; loc++) {
        distri_collect(r, length, loc);
    }


    /********** End **********/
    int p = r[0].next;
    for(i=0; i<length && p!=0; i++)
    {
        a[i] = r[p].data;
        p = r[p].next;
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    int i;
    int * a=(int*)malloc(sizeof(int)*n);
    for (i=0; i<n; i++) scanf("%d", &a[i]);
    RadixSort(a,n,2);
    for (i=0; i<n; i++) printf("%d ", a[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸦羽FadingRaven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值