一-顺序表
运行结果:
输入6个整型数据:
1
2
3
4
5
6
您输入的数据为:1 2 3 4 5 6
选择进行的操作:1.插入数据 2.删除数据 3.退出程序
1
输入插入的位置:2
输入数据:100
插入成功
1 100 2 3 4 5 6
选择进行的操作:1.插入数据 2.删除数据 3.退出程序
1
输入插入的位置:10
输入数据:100
插入失败
1 100 2 3 4 5 6
选择进行的操作:1.插入数据 2.删除数据 3.退出程序
2
输入删除的位置:4
删除成功
1 100 2 4 5 6
选择进行的操作:1.插入数据 2.删除数据 3.退出程序
3
退出程序
请按任意键继续. . .
源代码:
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 6
#define LIST_TNCREMENT 2
typedef int ElenType;
typedef struct
{
ElenType *data; // 每个元素的数据类型
int length; // 一共有多少个元素
int listsize; // 整个顺序表的长度
} SqList;
// 初始化一个顺序表
int initList(SqList *L)
{
// 1.申请一个空间
L->data = (ElenType *)malloc(MaxSize * sizeof(ElenType));
// 2.判断是否拿到了空间内存
if (!L->data)
exit(-1);
// 3.如果拿到了内存空间,就需要初始化顺序表
L->length = 0;
L->listsize = MaxSize;
return 1;
}
// 放入数据
void data_ttt(SqList *L)
{
int a;
printf("输入6个整型数据:\n");
for (int i = 0; i < 6; i++)
{
scanf("%d", &a);
L->data[i] = a;
L->length++;
}
printf("您输入的数据为:%d %d %d %d %d %d\n", L->data[0], L->data[1], L->data[2], L->data[3], L->data[4], L->data[5]);
}
// 扩大数组的长度+2
int extantList(SqList *L)
{
// 重新申请内存
ElenType *p = (ElenType *)realloc(L->data, (L->listsize + LIST_TNCREMENT) * sizeof(ElenType));
// 判断是否申请到了内存
if (!p)
exit(-1);
// 如果申请到了内存就要更新顺序表的信息
L->data = p;
L->listsize += LIST_TNCREMENT;
return 1;
}
// 插入数据
int insert(SqList *L)
{
int i, j;
// int a;
printf("输入插入的位置:");
scanf("%d", &i);
printf("输入数据:");
scanf("%d", &j);
if ((i < 1) || (i > L->length + 1))
{
printf("插入失败\n");
return 1;
}
// 判断表是否有空余空间,如果没有扩大表长
if (L->length >= L->listsize)
extantList(L);
for (int a = L->length - 1; a >= i - 1; a--)
L->data[a + 1] = L->data[a];
L->data[i - 1] = j;
L->length++;
printf("插入成功\n");
return 0;
}
// 删除数据
int deletedata(SqList *L)
{
int i, j;
printf("输入删除的位置:");
scanf("%d", &i);
if ((i < 1) || (i > L->length))
{
printf("删除失败\n");
return 1;
}
for (j = i; j <= L->length - 1; j++)
L->data[j - 1] = L->data[j];
L->length--;
printf("删除成功\n");
return 0;
}
// 遍历顺序表
void findAllList(SqList *L)
{
int i;
for (i = 0; i < L->length; i++)
{
printf("%d ", L->data[i]);
}
}
// 销毁顺序表
int deleteList(SqList *L)
{
// 判断顺序表是否存在
if (L->data == NULL)
return 0;
// 如果存在,则释放对应的内存
free(L->data);
// 释放内存之后,要恢复表的初始值
L->length = 0;
L->listsize = 0;
return 1;
}
int main()
{
int a;
int b;
SqList L;
initList(&L); // 初始化
data_ttt(&L); // 放入数据
while (1)
{
printf("\n");
printf("选择进行的操作:");
printf("1.插入数据 2.删除数据 3.退出程序\n");
scanf("%d", &a);
switch (a)
{
case 1:
insert(&L); // 插入数据
findAllList(&L); // 遍历顺序表
break;
case 2:
deletedata(&L);
findAllList(&L); // 遍历顺序表
break;
case 3:
// 退出循环
printf("退出程序\n");
deleteList(&L); // 释放顺序表的内存
system("pause");
exit(-1);
default:
printf("无效的选项,请重新选择\n");
}
}
// 释放顺序表的空间
deleteList(&L);
system("pause");
return 0;
}
二-单链表
运行结果:
输入5个单链表的数据:
1
2
3
4
5
成功创建链表:
1 2 3 4 5
*****1.单链表的插入******
*****2.单链表的删除******
*****3.单链表的查找******
*****4. 退出******
输入选项:
1
输入插入数据的位置:2
插入成功!输入插入数据的值:6
插入后的链表为: 1 6 2 3 4 5
*****1.单链表的插入******
*****2.单链表的删除******
*****3.单链表的查找******
*****4. 退出******
输入选项:1
输入插入数据的位置:9
插入失败!请重新输入
*****1.单链表的插入******
*****2.单链表的删除******
*****3.单链表的查找******
*****4. 退出******
输入选项:2
输入删除数据的位置:6
1 6 2 3 4
*****1.单链表的插入******
*****2.单链表的删除******
*****3.单链表的查找******
*****4. 退出******
输入选项:3
输入查找数据的位置:4
查找的元素为:3
*****1.单链表的插入******
*****2.单链表的删除******
*****3.单链表的查找******
*****4. 退出******
输入选项:0
无效的选项,请重新选择
*****1.单链表的插入******
*****2.单链表的删除******
*****3.单链表的查找******
*****4. 退出******
输入选项:4
退出程序
请按任意键继续. . .
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
typedef int ElemType;
// 定义链表节点结构体
typedef struct Node
{
ElemType data; // 数据域
struct Node *next; // 指针域,指向下一个节点
} Node, *LinkedList;
// 建立菜单
void menu()
{
printf("*****1.单链表的插入******\n");
printf("*****2.单链表的删除******\n");
printf("*****3.单链表的查找******\n");
printf("*****4. 退出******\n");
}
// 初始化链表函数,将链表头指针设为NULL
LinkedList LinkListInit()
{
Node *L;
L = (Node *)malloc(sizeof(Node));
if (L == NULL)
{
printf("申请内存空间失败");
}
L->next = NULL; // 将链表头指针设为NULL
return L; // 返回初始化成功
}
// 单链表的建立(头插法)
LinkedList ListCreatH()
{
Node *L;
L = (Node *)malloc(sizeof(Node));
L->next = NULL;
int i = 0;
ElemType x;
while (i < 10)
{
Node *p;
p = (Node *)malloc(sizeof(Node));
scanf("%d", &x);
p->data = x;
p->next = L->next;
L->next = p;
;
i++;
}
return L;
}
LinkedList List_creatT(LinkedList &L)
{
Node *list;
list = (Node *)malloc(sizeof(Node));
list->next = NULL;
L = list;
Node *r;
r = L;
int i = 0;
for (i = 0; i < 5; i++)
{
Node *p;
p = (Node *)malloc(sizeof(Node));
scanf("%d", &p->data);
r->next = p;
r = p;
}
r->next = NULL;
return L;
}
// 在链表中插入元素的函数,将元素e插入到链表的第i个位置
bool ListInsert(LinkedList &L, int i, int x)
{
if (i < 1) // 如果插入位置小于1,插入失败,返回false
return false;
Node *p; // 定义指针p,用于遍历链表
int j = 0; // 定义计数器j,用于记录当前遍历到的位置
p = L; // 将指针p指向链表头指针
while (p != NULL && j < i - 1)
{ // 遍历链表,直到找到第i-1个位置或到达链表尾部
p = p->next; // 将指针p指向下一个节点
j++; // 计数器j加1
if (p == NULL) // 如果到达链表尾部,插入失败,返回false
return false;
}
Node *s = (Node *)malloc(sizeof(Node)); // 分配内存空间,创建新节点s
s->data = x; // 将新节点的数据域赋值为e
s->next = p->next; // 将新节点的指针域指向原第i个节点的下一个节点
p->next = s; // 将原第i个节点的指针域指向新节点s
return true; // 插入成功,返回true
}
// 删除链表中第i个元素,并将该元素的值赋给e
bool ListDelete(LinkedList &L, int i, ElemType &x)
{
// 如果i小于1,返回false
if (i < 1)
return false;
// 初始化指针p指向头结点
Node *p = L;
// 初始化计数器j为0
int j = 0;
// 循环找到第i-1个结点
while (p != NULL && j < i - 1)
{
p = p->next;
j++;
}
// 如果p为NULL或者p->next为NULL,说明i值不合法,返回false
if (p == NULL || p->next == NULL)
return false;
// 初始化指针q指向被删除结点的下一个结点
Node *q = p->next;
// 将被删除结点的值为赋给x
x = q->data;
// 将p的next指向被删除结点的下一个结点
p->next = q->next;
// 释放被删除结点的内存空间
free(q);
// 删除成功,返回true
return true;
}
// 按位查找,返回第 i个元素(带头结点)
Node *SetElem(LinkedList L, int i)
{
if (i <= 0)
{ // 如果i小于等于0,返回NULL
return NULL;
}
Node *p = L; // 指针p指向当前扫描到的结点
int j = 0; // 当前p指向的是第几个结点
while (p != NULL && j < i)
{ // 循环找到第i个结点
p = p->next;
j++;
}
if (j == i)
{ // 如果找到了第i个结点
return p; // 返回该结点
}
else
{
return NULL; // 如果没有找到第i个结点,返回NULL
}
}
// 链表的销毁
void freeLink(Node *head)
{
// 判断链表是否为空,如果为空 ,则返回
if (head == NULL)
return;
// 如果非空,则逐个结点释放
Node *p, *q;
p = head;
while (p->next != NULL)
{
q = p->next;
p->next = q->next;
free(q);
}
free(head);
}
int main()
{
LinkedList List, start;
printf("输入5个单链表的数据:\n");
List = List_creatT(List);
printf("成功创建链表:\n");
for (start = List->next; start != NULL; start = start->next)
{
printf(" %d", start->data);
}
printf("\n");
int i, option;
int x;
while (1)
{
printf("\n");
menu();
printf("\n");
printf("输入选项:");
scanf("%d", &option);
switch (option)
{
case 1:
{
printf("输入插入数据的位置:");
scanf("%d", &i);
if (i > 0 && i < 6)
{
printf("插入成功!");
}
else
{
printf("插入失败!请重新输入");
break;
}
printf("输入插入数据的值:");
scanf("%d", &x);
ListInsert(List, i, x);
printf("插入后的链表为:");
for (start = List->next; start != NULL; start = start->next)
{
printf(" %d", start->data);
}
printf("\n");
break;
}
case 2:
{
printf("输入删除数据的位置:");
scanf("%d", &i);
ElemType e;
ListDelete(List, i, e);
for (start = List->next; start != NULL; start = start->next)
{
printf(" %d", start->data);
}
printf("\n");
break;
}
case 3:
{
int i;
printf("输入查找数据的位置:");
scanf("%d", &i);
Node *result = SetElem(List, i);
if (result != NULL)
{
printf("查找的元素为:%d\n", result->data);
}
else
{
printf("未找到元素或输入位置无效。\n");
}
break;
}
case 4:
{
printf("退出程序\n");
freeLink(List);
return 0;
}
default:
printf("无效的选项,请重新选择\n");
}
}
system("pause");
return 0;
}
三-顺序栈
运行结果:
******************
** 1.入栈
** 2.求栈顶元素
** 3.出栈
** 4.清空栈
** 5.遍历栈
** 0.退出程序
*****************
1
请输入入栈元素个数:8
请依次输入元素:
1
2
3
4
5
6
7
8
添加成功
顺序栈的元素如下:(从栈底到栈顶)
1 2 3 4 5 6 7 8
栈的长度为:8
******************
** 1.入栈
** 2.求栈顶元素
** 3.出栈
** 4.清空栈
** 5.遍历栈
** 0.退出程序
*****************
2
栈顶元素为8
******************
** 1.入栈
** 2.求栈顶元素
** 3.出栈
** 4.清空栈
** 5.遍历栈
** 0.退出程序
*****************
3
请输入出栈元素个数:4
成功弹出元素:8
成功弹出元素:7
成功弹出元素:6
成功弹出元素:5
顺序栈的元素如下:(从栈底到栈顶)
1 2 3 4
栈的长度为:4
******************
** 1.入栈
** 2.求栈顶元素
** 3.出栈
** 4.清空栈
** 5.遍历栈
** 0.退出程序
*****************
5
顺序栈的元素如下:(从栈底到栈顶)
1 2 3 4
栈的长度为:4
******************
** 1.入栈
** 2.求栈顶元素
** 3.出栈
** 4.清空栈
** 5.遍历栈
** 0.退出程序
*****************
4
成功清空
******************
** 1.入栈
** 2.求栈顶元素
** 3.出栈
** 4.清空栈
** 5.遍历栈
** 0.退出程序
*****************
5
顺序栈为空
栈的长度为:0
******************
** 1.入栈
** 2.求栈顶元素
** 3.出栈
** 4.清空栈
** 5.遍历栈
** 0.退出程序
*****************
0
成功退出!
成功销毁
请按任意键继续. . .
源代码:
// 用C实现顺序栈
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef struct
{
int *top;
int *base;
int stackSize;
} Stack;
// 初始化栈
void initStack(Stack &s)
{
s.base = new int[MaxSize]; // 动态分配内存
if (!s.base)
exit(0);
s.top = s.base;
s.stackSize = MaxSize;
}
// 判断栈是否为空
int isEmpty(Stack s)
{
if (s.base == s.top)
return 1;
return 0;
}
// 求栈的长度
int stackLength(Stack s)
{
return s.top - s.base;
}
// 遍历栈
void displayStack(Stack s)
{
int length = stackLength(s);
if (length > 0)
{
printf("顺序栈的元素如下:(从栈底到栈顶)\n\n");
for (int i = 0; i < length; i++)
{
printf(" %d", s.base[i]);
}
printf("\n");
}
else
{
printf("顺序栈为空\n\n");
}
printf("\n");
printf("栈的长度为:%d\n\n", stackLength(s));
}
// 清空栈
void CleanStack(Stack &s)
{
if (s.base)
{
s.base = s.top;
printf("成功清空\n\n");
}
else
{
printf("栈已被销毁 ,无需清空\n\n");
}
}
// 销毁栈
void DestoryStack(Stack &s)
{
if (s.base != NULL)
{
s.stackSize = 0;
s.base = NULL;
s.top = NULL;
delete s.base;
printf("成功销毁\n\n ");
}
else
{
printf("栈已被销毁 ,无需销毁\n\n");
}
}
// 入栈
void push(Stack &s, int e)
{
int n;
printf("请输入入栈元素个数:");
scanf("%d", &n);
printf("请依次输入元素:\n");
if ((s.top - s.base) == s.stackSize)
{
printf("栈满了,无法添加新元素!\n\n");
}
else
{
// 用for循环实现连续入栈
for (int i = 0; i < n; i++)
{
scanf("%d", &e);
*s.top++ = e;
}
printf("添加成功\n");
displayStack(s);
}
}
// 出栈
int pop(Stack &s, int &e)
{
int n;
printf("请输入出栈元素个数:");
scanf("%d", &n);
if (isEmpty(s))
{
printf("栈为空,无法弹出!\n\n");
return -1;
}
else
{
// 使用for循环连续出栈
for (int i = 0; i < n; i++)
{
e = *(s.top);
s.top--;
printf("成功弹出元素:%d\n\n", *(s.top));
}
displayStack(s);
return 1;
}
return 1;
}
// 求栈顶元素
int top(Stack s)
{
if (isEmpty(s))
{
printf("栈为空,没有栈顶元素!\n\n");
return 0;
}
else
{
s.top--;
return *(s.top);
}
}
// 菜单
void menu()
{
printf("******************\n");
printf("** 1.入栈 \n");
printf("** 2.求栈顶元素 \n");
printf("** 3.出栈 \n");
printf("** 4.清空栈 \n");
printf("** 5.遍历栈 \n");
printf("** 0.退出程序 \n");
printf("*****************\n\n");
}
int main()
{
char choice;
Stack s;
initStack(s); // 初始化栈
int e1, e2;
while (1)
{
menu();
scanf("%d", &choice);
switch (choice)
{
case 1:
push(s, e1);
break;
case 2:
if (top(s) != -1)
printf("栈顶元素为%d\n\n", top(s));
break;
case 3:
pop(s, e2);
break;
case 4:
CleanStack(s);
break;
case 5: // 遍历栈
displayStack(s);
break;
case 0:
printf("成功退出!\n\n");
DestoryStack(s); // 销毁栈
exit(0);
break;
default:
printf("输入有误,请重新输入\n\n");
break;
}
}
system("pause");
return 0;
}
四-顺序循环队列
运行结果:
******************
** 1.入队
** 2.取队头元素
** 3.出队
** 4.清空队列
** 0.退出程序
*****************
请选择:
1
请输入入队元素个数:8
请依次输入元素:
1
2
3
4
5
6
7
8
添加成功
1 2 3 4 5 6 7 8
队列的长度为:8
请选择:
2
队头元素为:1
请选择:
3
请输入出队元素个数:4
成功弹出元素:1
成功弹出元素:2
成功弹出元素:3
成功弹出元素:4
5 6 7 8
队列的长度为:4
请选择:
4
清空队列
队列为空!
请选择:
0
成功退出!
请按任意键继续. . .
源代码:
// 用c实现顺序队列
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100 // 队列可能达到的最大长度
typedef int QElemType;
typedef struct
{
QElemType *base;
// QElemType data[MAXSIZE];
int front;
int rear;
} SqQueue;
// 循环队列的初始化
void InitQueue(SqQueue &Q)
{
Q.base = new int[MAXSIZE];
if (!Q.base)
{
printf("内存分配失败!\n");
exit(1);
}
Q.front = Q.rear = 0;
}
// 判断队列是否为空
bool QueueEmpty(SqQueue Q)
{
if (Q.front == Q.rear)
return true;
else
return false;
}
// 求队列的长度
int QueueLength(SqQueue Q)
{
// 返回Q的元素个数,即队列的长度
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}
// 遍历队列
void QueueTraverse(SqQueue Q)
{
int i;
if (QueueEmpty(Q))
{
printf("队列为空!\n");
return;
}
i = Q.front;
while (i != Q.rear)
{
printf(" %d ", Q.base[i]);
i = (i + 1) % MAXSIZE;
}
printf("\n");
printf("队列的长度为:%d\n\n", QueueLength(Q));
}
// 清空队列
void eClearQueu(SqQueue &Q)
{
Q.front = Q.rear = 0;
QueueTraverse(Q);
}
// 销毁队列
void DestroyQueue(SqQueue &Q)
{
free(Q.base);
Q.base = NULL;
Q.front = Q.rear = 0;
}
// 循环队列的入队
void EnQueue(SqQueue &Q, QElemType e)
{
int n;
printf("请输入入队元素个数:");
scanf("%d", &n);
printf("请依次输入元素:\n");
if ((Q.rear + 1) % MAXSIZE == Q.front) // 若尾指针在循环意义上加1后等于头指针,表队列满
{
printf("队列已满!\n");
return;
}
else
{
// 用for循环实现连续入队
for (int i = 0; i < n; i++)
{
scanf("%d", &e);
Q.base[Q.rear] = e; // 新元素插入队尾
Q.rear = (Q.rear + 1) % MAXSIZE; // 队尾指针加1
}
printf("添加成功\n");
QueueTraverse(Q);
return;
}
}
// 循环队列的出队
void DeQueue(SqQueue &Q, QElemType &e)
{
int n;
printf("请输入出队元素个数:");
scanf("%d", &n);
if (Q.front == Q.rear)
{
printf("队列已空!\n");
exit(1);
}
else
{
// 使用for循环连续出栈
for (int i = 0; i < n; i++)
{
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXSIZE;
printf("成功弹出元素:%d\n", e);
}
QueueTraverse(Q);
return;
}
}
// 取队头元素
QElemType GetHead(SqQueue Q)
{
if (Q.front != Q.rear)
{
return Q.base[Q.front]; // 返回队列头元素的值,队列头指针不变
}
else
{
printf("队列为空!\n");
exit(1);
}
}
// 菜单
void menu()
{
printf("******************\n");
printf("** 1.入队 \n");
printf("** 2.取队头元素 \n");
printf("** 3.出队 \n");
printf("** 4.清空队列 \n");
printf("** 0.退出程序 \n");
printf("*****************\n\n");
}
int main()
{
char choice;
int e;
SqQueue Q;
menu();
InitQueue(Q);
while (1)
{
printf("请选择:\n");
scanf("%d", &choice);
switch (choice)
{
case 1:
EnQueue(Q, e);
break;
case 2:
printf("队头元素为:%d\n", GetHead(Q));
break;
case 3:
// 出队
DeQueue(Q, e);
break;
case 4:
printf("清空队列\n");
eClearQueu(Q);
break;
case 0:
printf("成功退出!\n\n");
// 销毁队列
DestroyQueue(Q);
system("pause");
exit(-1);
// return 0;
break;
default:
printf("输入有误,请重新输入\n\n");
break;
}
}
system("pause");
return 0;
}
五-先序遍历建立二叉链表及前中后序遍历
运行结果:
********************************
***** 1.先序遍历建立二叉链表
***** 2.遍历函数
***** 3.显示二叉树信息
***** 4.退出
********************************
请选择:1
是否有左子树或者右子树,如果有,输入1 ,否则输入0
1
请输入结点的三个值
1
1
1
请输入结点标记:
A
是否有左子树或者右子树,如果有,输入1 ,否则输入0
1
请输入结点的三个值
2
2
2
请输入结点标记:
B
是否有左子树或者右子树,如果有,输入1 ,否则输入0
0
是否有左子树或者右子树,如果有,输入1 ,否则输入0
0
是否有左子树或者右子树,如果有,输入1 ,否则输入0
1
请输入结点的三个值
3
3
3
请输入结点标记:
C
是否有左子树或者右子树,如果有,输入1 ,否则输入0
0
是否有左子树或者右子树,如果有,输入1 ,否则输入0
0
创建成功!!!
********************************
***** 1.先序遍历建立二叉链表
***** 2.遍历函数
***** 3.显示二叉树信息
***** 4.退出
********************************
请选择:2
请选择遍历方式:
1.先序遍历
2.中序遍历
3.后序遍历
1
先序遍历结果:
A结点
一值:1 ,二值:1 ,三值:1.000000
B结点
一值:2 ,二值:2 ,三值:2.000000
C结点
一值:3 ,二值:3 ,三值:3.000000
********************************
***** 1.先序遍历建立二叉链表
***** 2.遍历函数
***** 3.显示二叉树信息
***** 4.退出
********************************
请选择:2
请选择遍历方式:
1.先序遍历
2.中序遍历
3.后序遍历
2
中序遍历结果:
B结点
一值:2 ,二值:2 ,三值:2.000000
A结点
一值:1 ,二值:1 ,三值:1.000000
C结点
一值:3 ,二值:3 ,三值:3.000000
********************************
***** 1.先序遍历建立二叉链表
***** 2.遍历函数
***** 3.显示二叉树信息
***** 4.退出
********************************
请选择:2
请选择遍历方式:
1.先序遍历
2.中序遍历
3.后序遍历
3
后序遍历结果:
B结点
一值:2 ,二值:2 ,三值:2.000000
C结点
一值:3 ,二值:3 ,三值:3.000000
A结点
一值:1 ,二值:1 ,三值:1.000000
********************************
***** 1.先序遍历建立二叉链表
***** 2.遍历函数
***** 3.显示二叉树信息
***** 4.退出
********************************
请选择:3
二叉树结点个数:3
二叉树左子树结点个数:1
二叉树右子树结点个数:1
二叉树叶子结点个数:2
二叉树的深度:2
二叉树度为1的结点个数:0
********************************
***** 1.先序遍历建立二叉链表
***** 2.遍历函数
***** 3.显示二叉树信息
***** 4.退出
********************************
请选择:4
二叉链表已销毁!谢谢使用!请按任意键继续. . .
源代码:
// 二叉树的实现
#include <stdio.h>
#include <stdlib.h>
// 链式存储
typedef struct
{
int dataA;
int dataB;
double dataC;
} Student; // 结点类型
typedef struct node
{
Student stu; // 数据域
char ch; // 标记
struct node *lchild, *rchild; // 指针域
} NOOE; // 结点类型
// 为结点的数据域输入值
void inputValue(Student *stu)
{
if (!stu)
return;
printf("请输入结点的三个值\n");
scanf("%d%d%lf", &stu->dataA, &stu->dataB, &stu->dataC);
}
// 创建结点
NOOE *createNode(Student *stu)
{
// 需要判断一下是否有stu
if (!stu)
return NULL;
// 创建结点
NOOE *newNode = (NOOE *)malloc(sizeof(NOOE));
// 判断是否拿到内存
if (!newNode)
return NULL;
// 将输入的参数赋值给新拿到的内存空间
newNode->stu = *stu;
printf("请输入结点标记:\n");
fflush(stdin); // standard input
scanf("%c", &newNode->ch);
newNode->lchild = newNode->rchild = NULL;
// 返回创建好的结点
return newNode;
}
// 初始化一个二叉树
NOOE *initTree(NOOE *root)
{
// 1。设置一个标记,告诉程序是否继续添加结点
int flag = 0;
printf("是否有左子树或者右子树,如果有,输入1 ,否则输入0\n");
scanf("%d", &flag);
// 2,如果继续添加结点,需要给结点初始化
if (flag == 1)
{
Student stu;
inputValue(&stu);
root = createNode(&stu);
// 3,继续左子树,继续添加右子树
root->lchild = initTree(root->lchild);
root->rchild = initTree(root->rchild); // 先序遍历
}
// 4,要返回创建的子树
return root;
}
// 销毁二叉树
void destroyTree(NOOE *root)
{
// 1,如果根结点为空,直接返回
if (root == NULL)
return;
// 2,如果根结点不为空,则需要销毁根结点
destroyTree(root->lchild);
destroyTree(root->rchild);
// 3,销毁根结点
free(root);
}
// 打印结点信息
void outputValue(Student *stu)
{
if (stu == NULL)
return;
printf("一值:%-5d,二值:%-5d,三值:%-5lf\n", stu->dataA, stu->dataB, stu->dataC);
}
// 遍历二叉树
// 先序遍历
void preOrder(NOOE *tree)
{
if (tree != NULL)
{
printf("%c结点\n", tree->ch);
outputValue(&tree->stu);
preOrder(tree->lchild);
preOrder(tree->rchild);
}
}
// 中序遍历
void inOrder(NOOE *tree)
{
if (tree != NULL)
{
inOrder(tree->lchild);
printf("%c结点\n", tree->ch);
outputValue(&tree->stu);
inOrder(tree->rchild);
}
}
// 后序遍历
void postOrder(NOOE *tree)
{
if (tree != NULL)
{
postOrder(tree->lchild);
postOrder(tree->rchild);
printf("%c结点\n", tree->ch);
outputValue(&tree->stu);
}
}
// 统计二叉树中的结点个数
int countTreeNode(NOOE *tree)
{
if (tree == NULL)
return 0;
return countTreeNode(tree->lchild) + countTreeNode(tree->rchild) + 1;
}
// 统计叶子结点个数
int countTreeLeaf(NOOE *tree)
{
if (tree == NULL)
return 0;
if (tree->lchild == NULL && tree->rchild == NULL)
return 1;
return countTreeLeaf(tree->lchild) + countTreeLeaf(tree->rchild);
}
// 计算二叉树的深度
int countTreeDepth(NOOE *tree)
{
if (tree == NULL)
return 0;
int lDepth = countTreeDepth(tree->lchild);
int rDepth = countTreeDepth(tree->rchild);
return lDepth > rDepth ? lDepth + 1 : rDepth + 1;
}
// 统计二叉树的度为1的结点个数
int countTreeDegree1(NOOE *tree)
{
if (tree == NULL)
return 0;
if (tree->lchild == NULL && tree->rchild == NULL)
return 0;
if (tree->lchild == NULL)
return 1 + countTreeDegree1(tree->rchild);
if (tree->rchild == NULL)
return 1 + countTreeDegree1(tree->lchild);
return countTreeDegree1(tree->lchild) + countTreeDegree1(tree->rchild);
}
// 显示二叉树信息函数
void showTreeInfo(NOOE *tree)
{
printf("\n");
int num = countTreeNode(tree);
printf("二叉树结点个数:%d\n", num);
printf("二叉树左子树结点个数:%d\n", countTreeNode(tree->lchild));
printf("二叉树右子树结点个数:%d\n", countTreeNode(tree->rchild));
printf("二叉树叶子结点个数:%d\n", countTreeLeaf(tree));
printf("二叉树的深度:%d\n", countTreeDepth(tree));
printf("二叉树度为1的结点个数:%d\n", countTreeDegree1(tree));
printf("\n");
}
// 综合遍历函数
void showTree(NOOE *tree)
{
// 用户通过选择遍历方式打印二叉树
int choose;
printf("请选择遍历方式:\n");
printf("1.先序遍历\n");
printf("2.中序遍历\n");
printf("3.后序遍历\n");
printf("\n");
scanf("%d", &choose);
switch (choose)
{
case 1:
printf("先序遍历结果:\n");
preOrder(tree);
printf("\n");
break;
case 2:
printf("中序遍历结果:\n");
inOrder(tree);
printf("\n");
break;
case 3:
printf("后序遍历结果:\n");
postOrder(tree);
printf("\n");
break;
}
}
// 菜单函数
void menu()
{
printf("********************************\n");
printf("***** 1.先序遍历建立二叉链表 \n");
printf("***** 2.遍历函数 \n");
printf("***** 3.显示二叉树信息 \n");
printf("***** 4.退出 \n");
printf("********************************\n");
}
int main()
{
NOOE *tree = NULL;
while (1)
{
menu();
int choose;
printf("请选择:");
scanf("%d", &choose);
switch (choose)
{
case 1:
tree = initTree(tree);
printf("创建成功!!!\n\n");
break;
case 2:
showTree(tree);
break;
case 3:
showTreeInfo(tree);
break;
case 4:
printf("二叉链表已销毁!");
destroyTree(tree);
printf("谢谢使用!");
system("pause");
exit(0);
break;
default:
printf("输入错误,请重新输入!");
break;
}
}
system("pause");
return 0;
}
六-无向图的邻接矩阵构造与深度广度遍历
运行结果:
请输入图的总顶点数和总边数:
8
9
输入邻接矩阵各个顶点的信息:
1
2
3
4
5
6
7
8
输入边(Vi, Vj)上的下标Vi和Vj及权值w:
0
1
1
边(V0, V1)的权值为1
0
2
1
边(V0, V2)的权值为1
1
3
1
边(V1, V3)的权值为1
1
4
1
边(V1, V4)的权值为1
3
7
1
边(V3, V7)的权值为1
4
7
1
边(V4, V7)的权值为1
2
5
1
边(V2, V5)的权值为1
2
6
1
边(V2, V6)的权值为1
5
6
1
边(V5, V6)的权值为1
无向图邻接矩阵输出如下:
0 1 1 0 0 0 0 0
1 0 0 1 1 0 0 0
1 0 0 0 0 1 1 0
0 1 0 0 0 0 0 1
0 1 0 0 0 0 0 1
0 0 1 0 0 0 1 0
0 0 1 0 0 1 0 0
0 0 0 1 1 0 0 0
深度优先遍历DFS:
1 2 4 8 5 3 6 7
广度优先遍历BFS:
1 2 3 4 5 6 7 8
请按任意键继续. . .
源代码:
// C实现图
// 构造无向连通图,采用邻接矩阵作为图的存储结构,输出邻接矩阵,完成图的 DFS (深度优先遍历)和 BFS (广度优先遍历)的操作。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 图的邻接矩阵存储表示
#define MaxInt 32767 // 表示极大值和队列可能达到的最大长度
// 最大顶点数
#define MVNum 100
// 深度优先遍历标记符
bool flag[MVNum];
// 广度优先遍历标记符
bool visited[MVNum];
// 假设顶点的数据类型为字符型
typedef char VerTexType;
// 假设边的权值类型为整型
typedef int OtherInfo;
typedef struct
{
VerTexType vexs[MVNum]; // 顶点表
int arcs[MVNum][MVNum]; // 邻接矩阵
int vexnum, arcnum; // 图的当前顶点数和边数
} AMGraph;
// 为广度优先遍历构造队列
typedef int QElemType;
typedef struct
{
QElemType *base; // 初始化的动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;
void InitQueue(SqQueue &Q)
{
// 构造一个空队列Q
Q.base = new QElemType[MVNum];
if (!Q.base)
exit(-1);
Q.front = Q.rear = 0;
}
bool QueueEmpty(SqQueue Q)
{
// 判断队列是否为空,若为空返回true,否则返回false
if (Q.front == Q.rear)
return true;
else
return false;
}
// 入队
void EnQueue(SqQueue &Q, QElemType e)
{
// 插入元素e为Q的新的队尾元素
if ((Q.rear + 1) % MVNum == Q.front)
exit(-1);
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MVNum;
}
// 出队
bool DeQueue(SqQueue &Q, QElemType &e)
{
// 若队列不空,则删除Q的队头元素,用e返回其值,并返回true,否则返回false
if (Q.front == Q.rear)
return false;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MVNum;
return true;
}
// 确定v1和v2在G中的位置
int LocateVEX(AMGraph &G, VerTexType v)
{
int i;
for (i = 0; i < G.vexnum; i++)
{
if (G.vexs[i] == v)
return i;
}
return -1;
}
// 采用邻接矩阵表示法创建无向网
// 若要建立无向图,一是初始化邻接矩阵时,将边的权值均初始化化为0,二是在构造邻接矩阵时,将权值w改为常量1即可。
AMGraph CreateUDN(AMGraph &G)
{
int i, j, k;
int v1, v2;
OtherInfo w;
printf("请输入图的总顶点数和总边数:\n");
scanf("%d%d", &G.vexnum, &G.arcnum);
// 依次输入点的信息
printf("输入邻接矩阵各个顶点的信息: \n");
for (i = 0; i < G.vexnum; i++)
{
getchar();
scanf("%c", &G.vexs[i]);
}
// 初始化邻接矩阵,边的权值均置为极大值MaxInt
for (i = 0; i < G.vexnum; i++)
for (j = 0; j < G.vexnum; ++j)
// G.arcs[i][j] = MaxInt;
G.arcs[i][j] = 0;
// 构造邻接矩阵
printf("输入边(Vi, Vj)上的下标Vi和Vj及权值w:\n");
for (k = 0; k < G.arcnum; k++)
{
// 输入一条边依附的顶点及权值
scanf("%d%d%d", &v1, &v2, &w);
printf("边(V%d, V%d)的权值为%d\n", v1, v2, w);
// 确定v1和v2在G中的位置,即顶点数组的下标
i = LocateVEX(G, G.vexs[v1]);
j = LocateVEX(G, G.vexs[v2]);
G.arcs[i][j];
// 将<v1,v2>的权值设置为w
// G.arcs[i][j] = w;
G.arcs[i][j] = 1;
// 无向图的邻接矩阵是对称矩阵,即将<v2,v1>的权值设置为w
G.arcs[j][i] = G.arcs[i][j];
}
printf("\n无向图邻接矩阵输出如下:\n");
for (i = 0; i < G.vexnum; i++)
{
for (j = 0; j < G.vexnum; j++)
printf("%-3d", G.arcs[i][j]);
printf("\n");
}
printf("\n");
return G;
}
// 深度优先遍历无向连通图
void DFS(AMGraph G, int v)
{
// 从第v个顶点出发递归地深度优先遍历图G
// 访问第v个顶点,并置访问标志数组相应分量值为true
printf("%-3c", G.vexs[v]);
flag[v] = true;
// 判断是否存在邻接点
if (G.arcs[v][0] != MaxInt)
// 依次检查v所有邻接点w
for (int w = 0; w < G.vexnum; w++)
if (G.arcs[v][w] == 1 && flag[w] == false)
{
flag[w] = true; // 修正:将访问标志置为true
DFS(G, w); // 对v的尚未访问的邻接顶点w递归调用DFS()
}
}
// 广度优先遍历无向连通图
void BFS(AMGraph G)
{
int u, v;
SqQueue Q;
// 初始化所有顶点的访问标记为false
for (v = 0; v < G.vexnum; v++)
visited[v] = false;
// 初始化队列
InitQueue(Q);
// 从每个未访问的顶点开始进行BFS
for (u = 0; u < G.vexnum; u++)
{
if (!visited[u])
{
// 标记当前顶点为已访问,并输出
visited[u] = true;
printf("%-3c", G.vexs[u]);
// 将当前顶点入队
EnQueue(Q, u);
// 开始BFS
while (!QueueEmpty(Q))
{
// 出队一个顶点
DeQueue(Q, u);
// 遍历u的所有邻接顶点
for (v = 0; v < G.vexnum; v++)
{
// 如果u和v相邻且v未被访问过
if (G.arcs[u][v] != 0 && G.arcs[u][v] != MaxInt && !visited[v])
{
// 标记v为已访问,并输出
printf("%-3c", G.vexs[v]);
visited[v] = true;
// 将v入队,以便继续访问其邻接顶点
EnQueue(Q, v);
}
}
}
}
}
}
int main()
{
int i;
// 创建无向图邻接矩阵
AMGraph G;
CreateUDN(G);
// 深度优先遍历图G
printf("深度优先遍历DFS:\n ");
DFS(G, i);
printf("\n");
printf("广度优先遍历BFS:\n ");
BFS(G);
printf("\n");
system("pause");
return 0;
}
七-查找算法(顺序,折半,分块)
运行结果:
请输入查找表的长度:
8
输入表中的数据元素:
1
2
3
4
5
6
7
8
请输入要查找的关键字:
4
***********************
* 请选择要查找的方式
* 1.顺序查找
* 2.折半查找
* 3.分块查找
* 0.退出
***********************
1
顺序查找成功!关键字4的位置为4
查找次数为4
***********************
* 请选择要查找的方式
* 1.顺序查找
* 2.折半查找
* 3.分块查找
* 0.退出
***********************
2
折半查找成功!关键字4的位置为4
查找次数为1
***********************
* 请选择要查找的方式
* 1.顺序查找
* 2.折半查找
* 3.分块查找
* 0.退出
***********************
3
分块查找成功!关键字4的位置为4
查找次数为4
***********************
* 请选择要查找的方式
* 1.顺序查找
* 2.折半查找
* 3.分块查找
* 0.退出
***********************
0
谢谢使用!请按任意键继续. . .
源代码:
// 顺序查找的C实现
#include <stdio.h>
#include <stdlib.h>
typedef int KeyType;
typedef struct
{
KeyType key; // 关键字域
} ElemType;
typedef struct
{
ElemType *elem; // 数据元素存储基址,动态分配数组
int length; // 表长度
} SSTable;
// 创建查找表
SSTable *Create(int length)
{
SSTable *st = (SSTable *)malloc(sizeof(SSTable));
st->length = length;
st->elem = (ElemType *)malloc((length + 1) * sizeof(ElemType)); // 数组下标从1开始
printf("输入表中的数据元素:\n");
for (int i = 1; i <= length; i++)
{
scanf("%d", &(st->elem[i].key));
}
return st;
}
// 销毁查找表
void Destroy(SSTable *st)
{
free(st->elem); // 释放数据元素存储空间
free(st); // 释放查找表存储空间
}
// 在顺序表st中顺序查找其关键字等于Key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
int Search_Seq(SSTable *st, KeyType Key, int *searchCount)
{
int i;
*searchCount = 0; // 初始化查找次数为0
st->elem[0].key = Key; // 将关键字作为一个数据元素存放到查找表的第一个位置,起监视哨的作用
for (i = st->length; st->elem[i].key != Key; --i)
{
(*searchCount)++; // 增加查找次数
if (i == 0)
{
return 0;
}
}
return i;
}
// 折半查找
int Search_Bin(SSTable *st, KeyType Key, int *searchCount)
{
int low = 1;
int high = st->length;
int mid;
*searchCount = 0; // 初始化查找次数为0
while (low <= high)
{
mid = low + (high - low) / 2;
(*searchCount)++; // 增加查找次数
if (st->elem[mid].key == Key)
{
return mid; // 找到了,返回位置
}
else if (st->elem[mid].key < Key)
{
low = mid + 1; // 在右半边查找
}
else
{
high = mid - 1; // 在左半边查找
}
}
return 0; // 没有找到,返回0
}
// 分块查找
int Search_Block(SSTable *st, KeyType Key, int *searchCount)
{
int i, j;
*searchCount = 0; // 初始化查找次数为0
// 设置块的大小,这里假设块的个数为 length/3
int blockSize = st->length / 3;
// 在块的索引表中查找关键字所在的块
for (i = 0; i < st->length / blockSize; i++)
{
(*searchCount)++; // 增加查找次数
if (Key <= st->elem[(i + 1) * blockSize].key)
{
// 在找到的块内进行顺序查找
for (j = i * blockSize + 1; j <= (i + 1) * blockSize; j++)
{
(*searchCount)++; // 增加查找次数
if (st->elem[j].key == Key)
{
return j; // 找到了,返回位置
}
}
break; // 查找结束,跳出循环
}
}
return 0; // 没有找到,返回0
}
// 显示菜单
void menu()
{
printf("***********************\n");
printf("* 请选择要查找的方式 \n");
printf("* 1.顺序查找 \n");
printf("* 2.折半查找 \n");
printf("* 3.分块查找 \n");
printf("* 0.退出 \n");
printf("***********************\n");
}
int main()
{
SSTable *st;
printf("请输入查找表的长度:\n");
int length;
scanf("%d", &length);
st = Create(length);
printf("请输入要查找的关键字:\n");
KeyType Key;
scanf("%d", &Key);
while (1)
{
menu();
int choose;
int pos, pos1, pos2;
int searchCount;
scanf("%d", &choose);
switch (choose)
{
case 1:
pos = Search_Seq(st, Key, &searchCount);
if (pos != 0)
{
printf("顺序查找成功!关键字%d的位置为%d\n", Key, pos);
printf("查找次数为%d\n", searchCount);
}
else
{
printf("查找失败,没有关键字为%d的数据元素\n", Key);
}
break;
case 2:
pos1 = Search_Bin(st, Key, &searchCount);
if (pos1 != 0)
{
printf("折半查找成功!关键字%d的位置为%d\n", Key, pos1);
printf("查找次数为%d\n", searchCount);
}
else
{
printf("查找失败,没有关键字为%d的数据元素\n", Key);
}
break;
case 3:
pos2 = Search_Block(st, Key, &searchCount);
if (pos2 != 0)
{
printf("分块查找成功!关键字%d的位置为%d\n", Key, pos2);
printf("查找次数为%d\n", searchCount);
}
else
{
printf("查找失败,没有关键字为%d的数据元素\n", Key);
}
break;
case 0:
Destroy(st); // 销毁查找表
printf("谢谢使用!");
system("pause");
exit(0);
break;
default:
printf("输入错误,请重新输入!");
break;
}
}
system("pause");
return 0;
}