数据结构头歌实验
数据结构与算法 - 线性表
第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;
}