数据结构与算法
核心逻辑
- 定义
- 初始化创建数据结构
- 增加
- 删除
- 打印
- 可能会有判断空/满情况
链表
单链表
c
#include<stdlib.h>
typedef struct list{
int data;
struct list *next;
}node;
node* creatlisthead()
{
node* head=(node*)malloc(sizeof(node));
head->next=NULL;
return head;
}
void headsert(node*head,int data)
{
node*p=(node*)malloc(sizeof(node));
p->data=data;
p->next=head->next;
head->next=p;
}
void tailsert(node*head,int data)
{
node*p=(node*)malloc(sizeof(node));
p->data=data;
p->next=NULL;
node*list=head;
while(list->next)
{
list=list->next;
}
list->next=p;
}
void deletelist(node*head,int data)
{
node* list=head;
while(list->next)
{
if(list->next->data==data)
{
list->next=list->next->next;
return ;
}
list=list->next;
}
}
void print(node*head)
{
node* list=head->next;
while(list)
{
printf("%d",list->data);
list=list->next;
}
}
int main()
{
node *head=creatlisthead();
headsert(head,1);
headsert(head,2);
headsert(head,3);
deletelist(head,3);
tailsert(head,4);
tailsert(head,5);
deletelist(head,5);
tailsert(head,6);
deletelist(head,6);
print(head);
return 0;
}`
循环链表
c
#include<stdlib.h>
typedef struct list{
int data;
struct list *next;
}node;
node* creatlisthead()
{
node* head=(node*)malloc(sizeof(node));
head->next=head;
return head;
}
void headsert(node*head,int data)
{
node*p=(node*)malloc(sizeof(node));
p->data=data;
p->next=head->next;
head->next=p;
}
void tailsert(node*head,int data)
{
node*p=(node*)malloc(sizeof(node));
p->data=data;
node *list=head;
while(list->next!=head)
{
list=list->next;
}
list->next=p;
p->next=head;
}
void deletelist(node*head,int data)
{
node* list=head;
while(list->next!=head)
{
if(list->next->data==data)
{
list->next=list->next->next;
return ;
}
list=list->next;
}
}
void print(node*head)
{
node* list=head;
while(list->next!=head)
{
printf("%d->",list->next->data);
list=list->next;
}
printf("NULL");
}
int main()
{
node *head=creatlisthead();
headsert(head,1);
headsert(head,2);
headsert(head,3);
deletelist(head,3);
tailsert(head,4);
tailsert(head,5);
deletelist(head,5);
tailsert(head,6);
deletelist(head,6);
print(head);
return 0;
}`
双向链表
c
#include<stdlib.h>
typedef struct node{
int data;
struct node*pre;
struct node*next;
}Node;
Node* creathead()
{
Node*head=(Node*)malloc(sizeof(Node));
head->pre=NULL;
head->next=NULL;
return head;
}
void headsert(Node*head,int data)
{
Node*p=(Node*)malloc(sizeof(Node));
p->data=data;
if(head->next)
{
p->next=head->next;
p->pre=head;
head->next->pre=p;
head->next=p;
}else{
// 判断是否为空
p->next=head->next;
p->pre=head;
head->next=p;
}
}
void tailsert(Node*head,int data)
{
Node*p=(Node*)malloc(sizeof(Node));
p->data=data;
p->next=NULL;
Node*q=head;
while(q->next)
{
q=q->next;
}
p->pre=q;
q->next=p;
}
void del(Node*head,int data)
{
Node*p=head;
while(p->next)
{
if(p->data==data)
{
p->pre->next=p->next;
p->next->pre=p->pre;
return;
}
p=p->next;
}
p->pre->next=NULL;
}
void print(Node*head)
{
Node*list=head->next;
while(list)
{
printf("%d->",list->data);
list=list->next;
}
printf("NULL\n");
}
int main()
{
Node*head=creathead();
headsert(head,1);
headsert(head,2);
headsert(head,3);
del(head,3);
print(head);
tailsert(head,4);
tailsert(head,5);
tailsert(head,6);
del(head,6);
print(head);
return 0;
}`
双向循环链表
c
#include<stdlib.h>
typedef struct node{
int data;
struct node*pre;
struct node*next;
}Node;
Node* creathead()
{
Node*head=(Node*)malloc(sizeof(Node));
head->pre=head;//注意指向自己
head->next=head;
return head;
}
void headsert(Node*head,int data)
{
Node*p=(Node*)malloc(sizeof(Node));
p->data=data;
if(head->next)
{
p->next=head->next;
p->pre=head;
head->next->pre=p;
head->next=p;
}else{
// 判断是否为空
p->pre=head;
head->next=p;
p->next=head;
head->pre=p;
}
}
void tailsert(Node*head,int data)
{
Node*p=(Node*)malloc(sizeof(Node));
p->data=data;
Node*q=head;
while(q->next!=head)
{
q=q->next;
}
p->pre=q;
p->next=head;
q->next=p;
head->pre=p;
}
void del(Node*head,int data)
{
Node*p=head;
while(p->next!=head)
{
if(p->data==data)
{
p->pre->next=p->next;
p->next->pre=p->pre;
return;
}
p=p->next;
}
p->pre->next=head;
head->pre=p->pre;
}
void print(Node*head)
{
Node*list=head->next;
while(list!=head)
{
printf("%d->",list->data);
list=list->next;
}
printf("NULL\n");
}
int main()
{
Node*head=creathead();
headsert(head,1);
headsert(head,2);
headsert(head,3);
del(head,3);
print(head);
tailsert(head,4);
tailsert(head,5);
tailsert(head,6);
del(head,6);
print(head);
return 0;
}`
栈
c
#include<stdlib.h>
typedef struct node{
int data;
struct node*next;
}Node;
Node*creatstack()
{
Node*head=(Node*)malloc(sizeof(Node));
head->next=NULL;
return head;
}
void push(Node*head,int data)//采用头插法,因为出栈只能从头出,于是链表头为栈顶
{
Node*p=(Node*)malloc(sizeof(Node));
p->data=data;
p->next=head->next;
head->next=p;
}
int isempty(Node*head)
{
if(head->next)
return 0;
return 1;
}
void pop(Node*head)
{
if(head->next)
{
Node*p=head->next;
int a=p->data;
printf("pop=%d\n",a);
head->next=p->next;
head=p;//为什么有这一步
// free(p);
}else{
return;
}
}
void print(Node*head)
{
Node*p=head->next;
while(p)
{
printf("%d->",p->data);
p=p->next;
}
printf("NULL\n");
}
int main()
{
Node*head=creatstack();
push(head,1);
push(head,2);
push(head,3);
push(head,4);
print(head);
printf("poping\n");
pop(head);
print(head);
pop(head);
print(head);
pop(head);
print(head);
return 0;
}`
队列
一般
c
#include<stdlib.h>
typedef struct node{
int data;
struct node*next;
}Node;
Node*creatqueue()
{
Node*head=(Node*)malloc(sizeof(Node));
head->next=NULL;
return head;
}
void enqueue(Node*head,int data)//尾插法创建,因为头部要出队,头部为先进队的,所以,尾插法处理后进队的
{
Node*p=(Node*)malloc(sizeof(Node));
p->data=data;
Node*q=head;
while(q->next)
{
q=q->next;
}
p->next=q->next;
q->next=p;
}
void popqueue(Node*head)
{
if(head->next)
{
Node*p=head->next;
printf("pop=%d\n",p->data);
head->next=p->next;
head=p;
}else{
printf("NULL");
}
}
void print(Node*head)
{
Node*p=head->next;
while(p)
{
printf("%d->",p->data);
p=p->next;
}
printf("NULL");
}
int main()
{
Node*head=creatqueue();
enqueue(head,1);
enqueue(head,2);
enqueue(head,3);
print(head);
popqueue(head);
print(head);
popqueue(head);
print(head);
popqueue(head);
print(head);
return 0;
}`
循环队列
- 循环队列的长度表示 len=(head->rear-head->front+Max)%Max;
- rear及front的表示 head->front=(head->front+1)%Max;
- 取余时,小数取大数=小数,大数取小数=大数-小数,两数等为0
c
#include<stdlib.h>
#define Max 5
typedef struct node{
int data[Max];
int front;
int rear;
}Que;
Que* creatqueue()
{
Que* head=(Que*)malloc(sizeof(Que));
head->front=head->rear=0;
return head;
}
int isfull(Que*head)
{
if((head->rear+1)%Max==head->front)//判断队满
return 1;
return 0;
}
int isempty(Que*head)
{
if(head->front==head->rear)//判断队空
return 1;
return 0;
}
void enqueue(Que*head,int data)
{
if(isfull(head))
{
;
}else{
head->data[head->rear]=data;
head->rear=(head->rear+1)%Max;
//rear 处不放值
}
}
void delqueue(Que*head)
{
if(isempty(head))
{
;
}else{
printf("del=%d\n",head->data[head->front]);
head->front=(head->front+1)%Max;
//front 处有值
}
}
void print(Que*head)
{
int len=(head->rear-head->front+Max)%Max;
int index=head->front;
for(int i=0;i<len;i++)
{
printf("%d->",head->data[index]);
index++;
}
printf("NULL");
}
int main()
{
Que*q=creatqueue();
enqueue(q,1);
enqueue(q,2);
enqueue(q,3);
enqueue(q,4);
print(q);
delqueue(q);
print(q);
return 0;
}`
串
字符串暴力匹配
-
初始化字符串(数据域,字符串长度)
-
暴力匹配
c/** * File Name: ForceMatch.c * Author: tyrantlucifer * E-mail: tyrantlucifer@gmail.com * Blog: https://tyrantlucifer.com */ #include <stdio.h> #include <stdlib.h> /** * define struct of string */ typedef struct String { char* data; int len; } String; /** * init string * @return the pointer of string */ String* initString() { String* s = (String*)malloc(sizeof(String)); s->data = NULL; s->len = 0; return s; } /** * assign value to a string * @param s the pointer of string * @param data the value you want to assign */ void stringAssign(String* s, char* data) { if (s->data) { free(s->data); } int len = 0; char* temp = data; while (*temp) {//为什么不是temp len++; temp++; } if (len == 0) { s->data = NULL; s->len = 0; } else { temp = data; s->len = len; s->data = (char*)malloc(sizeof(char) * (len + 1));//指针使用要开辟空间 for (int i = 0; i < len; i++, temp++) { s->data[i] = *temp; } } } /** * print string * @param s the pointer of string */ void printString(String* s) { for (int i = 0; i < s->len; i++) { printf(i == 0 ? "%c " : "-> %c ", s->data[i]); } printf("\n"); } /** * force match * @param master the pointer of master string * @param sub the pointer of sub string */ void forceMatch(String* master, String* sub) { int i = 0; int j = 0; while (i < master->len && j < sub->len) { if (master->data[i] == sub->data[j]) { i++; j++; } else { i = i - j + 1; j = 0; } } if (j == sub->len) { printf("force match success.\n"); } else { printf("force match fail.\n"); } } /** * main function * @param argc the num of args * @param argv the array of args * @return null */ int main(int argc, char* argv[]) { String* s = initString(); String* s1 = initString(); stringAssign(s, argv[1]); stringAssign(s1, argv[2]); printString(s); printString(s1); forceMatch(s, s1); return 0; }
kmp算法
c
/**
* File Name: KMPMatch.c
* Author: tyrantlucifer
* E-mail: tyrantlucifer@gmail.com
* Blog: https://tyrantlucifer.com
*/
#include <stdio.h>
#include <stdlib.h>
/**
* define struct of string
*/
typedef struct String {
char* data;
int len;
} String;
/**
* init string
* @return the pointer of string
*/
String* initString() {
String* s = (String*)malloc(sizeof(String));
s->data = NULL;
s->len = 0;
return s;
}
/**
* assign value to a string
* @param s the pointer of string
* @param data the data you want to assign
*/
void stringAssign(String* s, char* data) {
if (s->data) {
free(s->data);
}
int len = 0;
char* temp = data;
while (*temp) {
len++;
temp++;
}
if (len == 0) {
s->data = NULL;
s->len = 0;
} else {
temp = data;
s->len = len;
s->data = (char*)malloc(sizeof(char) * (len + 1));
for (int i = 0; i < len; i++, temp++) {
s->data[i] = *temp;
}
}
}
/**
* print string
* @param s the pointer of string
*/
void printString(String* s) {
for (int i = 0; i < s->len; i++) {
printf(i == 0 ? "%c " : "-> %c ", s->data[i]);
}
printf("\n");
}
/**
* get next array for a string
* @param s the pointer of string
* @return the next array pointer
*/
int* getNext(String* s) {
int* next = (int*)malloc(sizeof(int) * s->len);
int i = 0;
int j = -1;
next[i] = j;
while (i < s->len - 1) {
if (j == -1 || s->data[i] == s->data[j]) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
return next;
}
/**
* print next array
* @param next the pointer of array
* @param len the len of next array
*/
void printNext(int* next, int len) {
for (int i = 0; i < len; i++) {
printf(i == 0 ? "%d " : "-> %d ", next[i] + 1);
}
printf("\n");
}
/**
* kmp match
* @param master the pointer of master string
* @param sub the pointer of sub string
* @param next the next array pointer array
*/
void kmpMatch(String* master, String* sub, int* next) {
int i = 0;
int j = 0;
while (i < master->len && j < sub->len) {
if (j == -1 || master->data[i] == sub->data[j]) {
i++;
j++;
} else {
j = next[j];
}
}
if (j == sub->len) {
printf("kmp match success.\n");
} else {
printf("kmp match fail.\n");
}
}
/**
* main function
* @param argc the num of args
* @param argv the array of args
* @return null
*/
int main(int argc, char* argv[]) {
String* s = initString();
String* s1 = initString();
stringAssign(s, argv[1]);
printString(s);
stringAssign(s1, argv[2]);
printString(s1);
int* next = getNext(s1);
printNext(next, s1->len);
kmpMatch(s, s1, next);
return 0;
}/**
* File Name: KMPMatch.cpp
* Author: tyrantlucifer
* E-mail: tyrantlucifer@gmail.com
* Blog: https://tyrantlucifer.com
*/
#include <stdio.h>
#include <stdlib.h>
/**
* define struct of string
*/
typedef struct String {
char* data;
int len;
} String;
/**
* init string
* @return the pointer of string
*/
String* initString() {
String* s = (String*)malloc(sizeof(String));
s->data = NULL;
s->len = 0;
return s;
}
/**
* assign value to a string
* @param s the pointer of string
* @param data the data you want to assign
*/
void stringAssign(String* s, char* data) {
if (s->data) {
free(s->data);
}
int len = 0;
char* temp = data;
while (*temp) {
len++;
temp++;
}
if (len == 0) {
s->data = NULL;
s->len = 0;
} else {
temp = data;
s->len = len;
s->data = (char*)malloc(sizeof(char) * (len + 1));
for (int i = 0; i < len; i++, temp++) {
s->data[i] = *temp;
}
}
}
/**
* print string
* @param s the pointer of string
*/
void printString(String* s) {
for (int i = 0; i < s->len; i++) {
printf(i == 0 ? "%c " : "-> %c ", s->data[i]);
}
printf("\n");
}
/**
* get next array for a string
* @param s the pointer of string
* @return the next array pointer
*/
int* getNext(String* s) {
int* next = (int*)malloc(sizeof(int) * s->len);
int i = 0;
int j = -1;
next[i] = j;
while (i < s->len - 1) {
if (j == -1 || s->data[i] == s->data[j]) {
i++;
j++;
next[i] = j;
} else {
j = next[j];
}
}
return next;
}
/**
* print next array
* @param next the pointer of array
* @param len the len of next array
*/
void printNext(int* next, int len) {
for (int i = 0; i < len; i++) {
printf(i == 0 ? "%d " : "-> %d ", next[i] + 1);
}
printf("\n");
}
/**
* kmp match
* @param master the pointer of master string
* @param sub the pointer of sub string
* @param next the next array pointer array
*/
void kmpMatch(String* master, String* sub, int* next) {
int i = 0;
int j = 0;
while (i < master->len && j < sub->len) {
if (j == -1 || master->data[i] == sub->data[j]) {
i++;
j++;
} else {
j = next[j];
}
}
if (j == sub->len) {
printf("kmp match success.\n");
} else {
printf("kmp match fail.\n");
}
}
/**
* main function
* @param argc the num of args
* @param argv the array of args
* @return null
*/
int main(int argc, char* argv[]) {
String* s = initString();
String* s1 = initString();
stringAssign(s, argv[1]);
printString(s);
stringAssign(s1, argv[2]);
printString(s1);
int* next = getNext(s1);
printNext(next, s1->len);
kmpMatch(s, s1, next);
return 0;
}
二叉树
基础
创建与遍历-左右孩子表示法
``
c
/*************************************************************************
* File Name: tree.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Sun 09 May 2021 08:47:34 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
char data;
struct TreeNode* lchild;
struct TreeNode* rchild;
}TreeNode;
void createTree(TreeNode** T, char* data, int* index) {
char ch;
ch = data[*index];
*index += 1;
if (ch == '#') {
// 此时为空节点
*T = NULL;
}
else {
// 此时不为空
*T = (TreeNode*)malloc(sizeof(TreeNode));//指针使用要么开辟空间,要么赋值(地址)
(*T) -> data = ch;
// 创建左子树,逻辑一致,进行递归
createTree(&((*T)->lchild), data, index);
// 创建右子树,逻辑一致,进行递归
createTree(&((*T)->rchild), data, index);
}
}
void preOrder(TreeNode* T) {
if (T == NULL) {
return;
}
else {
// 先办事
printf("%c ", T->data);
// 处理左孩子
preOrder(T->lchild);
// 处理右孩子
preOrder(T->rchild);
}
}
void inOrder(TreeNode* T) {
if (T == NULL) {
return;
}
else {
// 处理左孩子
inOrder(T->lchild);
// 中办事
printf("%c ", T->data);
// 处理右孩子
inOrder(T->rchild);
}
}
void postOrder(TreeNode* T) {
if (T == NULL) {
return;
}
else {
// 处理左孩子
postOrder(T->lchild);
// 处理右孩子
postOrder(T->rchild);
// 后办事
printf("%c ", T->data);
}
}
int main(int argc, char* argv[]) {
TreeNode* T;
int index = 0;
createTree(&T, argv[1], &index);
preOrder(T);
printf("\n");
inOrder(T);
printf("\n");
postOrder(T);
printf("\n");
return 0;
}
层序遍历
``
c
/*************************************************************************
* File Name: treeLevelTraverse.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Thu 13 May 2021 07:03:14 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
char data;
struct TreeNode* lchild;
struct TreeNode* rchild;
}TreeNode;
typedef struct QueueNode {
TreeNode* data;
struct QueueNode* pre;
struct QueueNode* next;
}QueueNode;
void createTree(TreeNode** T, char* data, int* index) {
char ch;
ch = data[*index];
*index += 1;
if (ch == '#') {
*T = NULL;
}
else {
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = ch;
createTree(&((*T)->lchild), data, index);
createTree(&((*T)->rchild), data, index);
}
}
void preOrder(TreeNode* T) {
if (T == NULL) {
return;
}
else {
printf("%c ", T->data);
preOrder(T->lchild);
preOrder(T->rchild);
}
}
QueueNode* initQueue() {
QueueNode* Q = (QueueNode*)malloc(sizeof(QueueNode));
Q->data = NULL;
Q->next = Q;
Q->pre = Q;
return Q;
}
void enQueue(TreeNode* data, QueueNode* Q) {
QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
node->data = data;
node->pre = Q;
node->next = Q;
Q->pre->next = node;
Q->pre = node;
}
int isEmpty(QueueNode* Q) {
if (Q->next == Q) {
return 1;
}
else {
return 0;
}
}
QueueNode* deQueue(QueueNode* Q) {
if (isEmpty(Q)) {
return NULL;
}
else {
QueueNode* node = Q->next;
Q->next->next->pre = Q;
Q->next = Q->next->next;
return node;
}
}
void levelTraverse(QueueNode* Q, TreeNode* T) {
enQueue(T, Q);//入队
while (!isEmpty(Q)) {//队不为空
QueueNode* node = deQueue(Q);//出队
printf("%c ", node->data->data);
if (node->data->lchild) {
enQueue(node->data->lchild, Q);//入队
}
if (node->data->rchild) {
enQueue(node->data->rchild, Q);//入队
}
}
}
int main (int argc, char* argv[]) {
TreeNode* T;
int index = 0;
QueueNode* Q = initQueue();
createTree(&T, argv[1], &index);
preOrder(T);
printf("\n");
levelTraverse(Q, T);
printf("\n");
return 0;
}
非递归遍历
先中序遍历
``
c
/*************************************************************************
* File Name: treeNonRecursive.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Sun 16 May 2021 05:51:25 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
char data;
struct TreeNode* lchild;
struct TreeNode* rchild;
}TreeNode;
typedef struct StackNode {
TreeNode* data;
struct StackNode* next;
}StackNode;
void createTree(TreeNode** T, char* data, int* index) {
char ch;
ch = data[*index];
*index += 1;
if (ch == '#') {
// 此时为空节点
*T = NULL;
}
else {
// 此时不为空
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = ch;
// 创建左子树,逻辑一致,进行递归
createTree(&((*T)->lchild), data, index);
// 创建右子树,逻辑一致,进行递归
createTree(&((*T)->rchild), data, index);
}
}
StackNode* initStack() {
StackNode* S = (StackNode*)malloc(sizeof(StackNode));
S->data = NULL;
S->next = NULL;
return S;
}
void push(TreeNode* data, StackNode* S) {
StackNode* node = (StackNode*)malloc(sizeof(StackNode));
node->data = data;
node->next = S->next;
S->next = node;
}
int isEmpty(StackNode* S) {
if (S->next == NULL) {
return 1;
}
else {
return 0;
}
}
StackNode* pop(StackNode* S) {
if (isEmpty(S)) {
return NULL;
}
else {
StackNode* node = S->next;
S->next = node->next;
return node;
}
}
void preOrder(TreeNode* T) {
TreeNode* node = T;
StackNode* S = initStack();//初始化栈
while (node || !isEmpty(S)) {
if (node) {
printf("%c ", node->data);
push(node, S);
node = node->lchild;
}
else {
node = pop(S) -> data;
node = node->rchild;
}
}
}
void inOrder(TreeNode* T) {
TreeNode* node = T;
StackNode* S = initStack();
while (node || !isEmpty(S)) {
if (node) {
push(node, S);
node = node->lchild;
}
else {
node = pop(S) -> data;
printf("%c ", node->data);
node = node->rchild;
}
}
}
int main(int argc, char* argv[]) {
TreeNode* T;
int index = 0;
createTree(&T, argv[1], &index);
preOrder(T);
printf("\n");
inOrder(T);
printf("\n");
return 0;
}
后序遍历
``
c
/*************************************************************************
* File Name: treeNonRecursivePost.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Sun 04 Jul 2021 02:24:42 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
char data;
struct TreeNode* lchild;
struct TreeNode* rchild;
int flag;
}TreeNode;
typedef struct StackNode {
TreeNode* data;
struct StackNode* next;
}StackNode;
void createTree(TreeNode** T, char* data, int* index) {
char ch;
ch = data[*index];
*index += 1;
if (ch == '#') {
// 此时为空节点
*T = NULL;
}
else {
// 此时不为空
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = ch;
(*T) -> flag = 0;
// 创建左子树,逻辑一致,进行递归
createTree(&((*T)->lchild), data, index);
// 创建右子树,逻辑一致,进行递归
createTree(&((*T)->rchild), data, index);
}
}
StackNode* initStack() {
StackNode* S = (StackNode*)malloc(sizeof(StackNode));
S->data = NULL;
S->next = NULL;
return S;
}
void push(TreeNode* data, StackNode* S) {
StackNode* node = (StackNode*)malloc(sizeof(StackNode));
node->data = data;
node->next = S->next;
S->next = node;
}
int isEmpty(StackNode* S) {
if (S->next == NULL) {
return 1;
}
else {
return 0;
}
}
StackNode* pop(StackNode* S) {
if (isEmpty(S)) {
return NULL;
}
else {
StackNode* node = S->next;
S->next = node->next;
return node;
}
}
StackNode* getTop(StackNode* S) {
if (isEmpty(S)) {
return NULL;
}
else {
StackNode* node = S->next;
return node;
}
}
void postOrder(TreeNode* T) {
TreeNode* node = T;
StackNode* S = initStack();
while (node || !isEmpty(S)) {
if (node) {
push(node, S);
node = node -> lchild;
}
else {
TreeNode* top = getTop(S) -> data;
if (top -> rchild && top -> rchild -> flag == 0) {
top = top -> rchild;
push(top, S);
node = top -> lchild;
}
else {
top = pop(S) -> data;
printf("%c ", top -> data);
top -> flag = 1;
}
}
}
}
int main(int argc, char* argv[]) {
TreeNode* T;
int index = 0;
createTree(&T, argv[1], &index);
postOrder(T);
printf("\n");
return 0;
}
线索二叉树
使用线索将二叉树转换为一个类似的线性结构
线索是将节点连在一起的指针
二叉树有2n个指针,n-1个指针指向节点,还剩n+1个指针用来指向二叉树遍历中时的前驱与后驱
中序线索二叉树
c
/*************************************************************************
* File Name: inThreadTree.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Wed 07 Jul 2021 09:14:08 PM CST
************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
char data;
struct TreeNode* lchild;
struct TreeNode* rchild;
int ltag;
int rtag;
}TreeNode;
void createTree(TreeNode** T, char* data, int* index) {
char ch;
ch = data[*index];
*index += 1;
if (ch == '#') {
// 此时为空节点
*T = NULL;
}
else {
// 此时不为空
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = ch;
(*T) -> ltag = 0;
(*T) -> rtag = 0;
// 创建左子树,逻辑一致,进行递归
createTree(&((*T)->lchild), data, index);
// 创建右子树,逻辑一致,进行递归
createTree(&((*T)->rchild), data, index);
}
}
void inThreadTree(TreeNode* T, TreeNode** pre) {
if (T) {
inThreadTree(T -> lchild, pre);
// do something
if (T -> lchild == NULL) {
T -> ltag = 1;
T -> lchild = *pre;
}
if (*pre != NULL && (*pre) -> rchild == NULL) {
(*pre) -> rtag = 1;
(*pre) -> rchild = T;
}
*pre = T;
//
inThreadTree(T -> rchild, pre);
}
}
TreeNode* getFirst(TreeNode* T) {
while (T -> ltag == 0)
T = T -> lchild;
return T;
}
TreeNode* getNext(TreeNode* node) {
if (node -> rtag == 1)
return node -> rchild;
else
return getFirst(node -> rchild);
}
int main(int argc, char* argv[]) {
TreeNode* T;
TreeNode* pre = NULL;
int index = 0;
createTree(&T, argv[1], &index);
inThreadTree(T, &pre);
pre -> rtag = 1;
pre -> rchild = NULL;
for (TreeNode* node = getFirst(T); node != NULL; node = getNext(node)) {
printf("%c ", node -> data);
}
printf("\n");
return 0;
}
先序线索二叉树
不懂
c
/*************************************************************************
* File Name: preThreadTree.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Wed 07 Jul 2021 09:14:08 PM CST
************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
char data;
struct TreeNode* lchild;
struct TreeNode* rchild;
int ltag;
int rtag;
}TreeNode;
void createTree(TreeNode** T, char* data, int* index) {
char ch;
ch = data[*index];
*index += 1;
if (ch == '#') {
// 此时为空节点
*T = NULL;
}
else {
// 此时不为空
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = ch;
(*T) -> ltag = 0;
(*T) -> rtag = 0;
// 创建左子树,逻辑一致,进行递归
createTree(&((*T)->lchild), data, index);
// 创建右子树,逻辑一致,进行递归
createTree(&((*T)->rchild), data, index);
}
}
void preThreadTree(TreeNode* T, TreeNode** pre) {
if (T) {
if (T -> lchild == NULL) {
T -> ltag = 1;
T -> lchild = *pre;
}
if (*pre != NULL && (*pre) -> rchild == NULL) {
(*pre) -> rtag = 1;
(*pre) -> rchild = T;
}
*pre = T;
if (T -> ltag == 0)
preThreadTree(T -> lchild, pre);
preThreadTree(T -> rchild, pre);
}
}
TreeNode* getNext(TreeNode* node) {
if (node -> rtag == 1 || node -> ltag == 1)
return node -> rchild;
else
return node -> lchild;
}
int main(int argc, char* argv[]) {
TreeNode* T;
TreeNode* pre = NULL;
int index = 0;
createTree(&T, argv[1], &index);
preThreadTree(T, &pre);
pre -> rtag = 1;
pre -> rchild = NULL;
for (TreeNode* node = T; node != NULL; node = getNext(node)) {
printf("%c ", node -> data);
}
printf("\n");
return 0;
}
后序线索二叉树
不懂
c
/*************************************************************************
* File Name: postThreadTree.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Wed 07 Jul 2021 09:14:08 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
typedef struct TreeNode {
char data;
struct TreeNode* lchild;
struct TreeNode* rchild;
struct TreeNode* parent;
int ltag;
int rtag;
}TreeNode;
void createTree(TreeNode** T, char* data, int* index, TreeNode* parent) {
char ch;
ch = data[*index];
*index += 1;
if (ch == '#') {
// 此时为空节点
*T = NULL;
}
else {
// 此时不为空
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = ch;
(*T) -> ltag = 0;
(*T) -> rtag = 0;
(*T) -> parent = parent;
// 创建左子树,逻辑一致,进行递归
createTree(&((*T)->lchild), data, index, *T);
// 创建右子树,逻辑一致,进行递归
createTree(&((*T)->rchild), data, index, *T);
}
}
void postThreadTree(TreeNode* T, TreeNode** pre) {
if (T) {
postThreadTree(T -> lchild, pre);
postThreadTree(T -> rchild, pre);
// do something
if (T -> lchild == NULL) {
T -> ltag = 1;
T -> lchild = *pre;
}
if (*pre != NULL && (*pre) -> rchild == NULL) {
(*pre) -> rtag = 1;
(*pre) -> rchild = T;
}
*pre = T;
}
}
TreeNode* getFirst(TreeNode* T) {
while (T -> ltag == 0)
T = T -> lchild;
if (T -> rtag == 0) {
return getFirst(T -> rchild);
}
return T;
}
TreeNode* getNext(TreeNode* node) {
if (node -> rtag == 1)
return node -> rchild;
else {
// 如果是根节点
if (node -> parent == NULL) {
return NULL;
}
// 如果是右孩子
else if (node -> parent -> rchild == node) {
return node -> parent;
}
// 如果是左孩子
else {
if (node -> parent -> ltag == 0) {
return getFirst(node -> parent -> rchild);
}
else {
return node -> parent;
}
}
}
}
int main(int argc, char* argv[]) {
TreeNode* T;
TreeNode* pre = NULL;
int index = 0;
createTree(&T, argv[1], &index, NULL);
postThreadTree(T, &pre);
for (TreeNode* node = getFirst(T); node != NULL; node = getNext(node)) {
printf("%c ", node -> data);
}
printf("\n");
return 0;
}
二叉排序树
c
/*************************************************************************
* File Name: binarySearchTree.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Wed 14 Jul 2021 11:11:49 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
int data;
struct TreeNode* lchild;
struct TreeNode* rchild;
}TreeNode;
TreeNode* bstSearch(TreeNode* T, int data) {
if (T) {
if (T -> data == data) {
return T;
}
else if (data < T -> data) {
return bstSearch(T -> lchild, data);
}
else {
return bstSearch(T -> rchild, data);
}
}
else {
return NULL;
}
}
void bstInsert(TreeNode** T, int data) {
if (*T == NULL) {
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = data;
(*T) -> lchild = NULL;
(*T) -> rchild = NULL;
}
else if (data == (*T) -> data) {
return;
}
else if (data < (*T) -> data) {
bstInsert(&((*T) -> lchild), data);
}
else {
bstInsert(&((*T) -> rchild), data);
}
}
void preOrder(TreeNode* T) {
if (T) {
printf("%d ", T -> data);
preOrder(T -> lchild);
preOrder(T -> rchild);
}
}
int main() {
TreeNode* T = NULL;
int nums[6] = {8, 6, 10, 9, 11, 23};
for (int i = 0; i < 6; i++) {
bstInsert(&T, nums[i]);
}
preOrder(T);
printf("\n");
}
平衡二叉树
什么是平衡二叉树
是一个合理的二叉树
如何保证合理
平衡二叉树左右子树高度茶不超过1
如何构建平衡二叉树
1.本质与构建二叉排序树一样
2.在构建二叉排序树时,发现树不合理,进行调整
如何判断调整类型
类型:
LL,RR,RL,LR
如何判断
1.找到失衡树的根节点--root
2.找到导致树失衡的结点--node,判断node在root的那一侧
3.判断node在root孩子的哪一侧
4.如果有多个树不平衡,选择最小树,开始
原理实现过程
1.RR型
取中间结点,作为父节点,让其父亲成为它的左孩子,若它本身有左孩子,则接到父亲的右孩子处
2.LL型
取中间结点,作为父节点,让其父亲成为它的右孩子,若他有右孩子,则接到父亲的左孩子处
3.LR型
取最后结点,作为父节点,让其父节点成为他的左孩子,让其父节点的父节点成为他的右孩子。
如果他有左孩子,则左孩子接到父节点的右孩子处,
如果他有右孩子,则右孩子接到父节点的父节点的左孩子处
4.RL型
取最后结点,作为父节点,让其父节点成为他的右孩子,让其父节点的父节点成为他的左孩子。
如果他有左孩子,则左孩子接到父节点的父节点的右孩子处,
如果他有右孩子,则右孩子接到父节点的左孩子处
代码实现过程
c
/*************************************************************************
* File Name: avlTree.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Sat 17 Jul 2021 06:24:32 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
int data;
int height;
struct TreeNode* lchild;
struct TreeNode* rchild;
}TreeNode;
int getHeight(TreeNode* node) {
return node ? node -> height : 0;
}
int max(int a, int b) {
return a > b ? a : b;
}
void rrRotation(TreeNode* node, TreeNode** root) {
TreeNode* temp = node -> rchild;
node -> rchild = temp -> lchild;
temp -> lchild = node;
node -> height = max(getHeight(node -> lchild), getHeight(node -> rchild)) + 1;
temp -> height = max(getHeight(temp -> lchild), getHeight(temp -> rchild)) + 1;
*root = temp;
}
void llRotation(TreeNode* node, TreeNode** root) {
TreeNode* temp = node -> lchild;
node -> lchild = temp -> rchild;
temp -> rchild = node;
node -> height = max(getHeight(node -> lchild), getHeight(node -> rchild)) + 1;
temp -> height = max(getHeight(temp -> lchild), getHeight(temp -> rchild)) + 1;
*root = temp;
}
void avlInsert(TreeNode** T, int data) {
if (*T == NULL) {
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T) -> data = data;
(*T) -> height = 0;
(*T) -> lchild = NULL;
(*T) -> rchild = NULL;
}
else if (data < (*T) -> data) {
avlInsert(&(*T) -> lchild, data);
// 拿到当前节点左右子树的高度
int lHeight = getHeight((*T) -> lchild);
int rHeight = getHeight((*T) -> rchild);
// 判断高度差
if (lHeight - rHeight == 2) {
if (data < (*T) -> lchild -> data) {
// LL 调整
llRotation(*T, T);
}
else {
// LR 调整
rrRotation((*T) -> lchild, &(*T) -> lchild);
llRotation(*T, T);
}
}
}
else if (data > (*T) -> data) {
avlInsert(&(*T) -> rchild, data);
// 拿到当前节点左右子树的高度
int lHeight = getHeight((*T) -> lchild);
int rHeight = getHeight((*T) -> rchild);
// 判断高度差
if (rHeight - lHeight == 2) {
if (data > (*T) -> rchild -> data) {
// RR 调整
rrRotation(*T, T);
}
else {
// RL 调整
llRotation((*T) -> rchild, &(*T) -> rchild);
rrRotation(*T, T);
}
}
}
(*T) -> height = max(getHeight((*T) -> lchild), getHeight((*T) -> rchild)) + 1;
}
void preOrder(TreeNode* T) {
if (T) {
printf("%d ", T -> data);
preOrder(T -> lchild);
preOrder(T -> rchild);
}
}
int main() {
TreeNode* T = NULL;
int nums[5] = {1,8,6,7,10};
for (int i = 0; i < 5; i++) {
avlInsert(&T, nums[i]);
}
preOrder(T);
printf("\n");
}
哈夫曼树
什么是哈夫曼树
使所有叶子结点的带权路径长度最小
代码实现
c
/*************************************************************************
* File Name: huffmanTree.c
* Author: TyrantLucifer
* E-mail: TyrantLucifer@gmail.com
* Blog: https://tyrantlucifer.com
* Created Time: Wed 21 Jul 2021 08:57:59 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
int parent;
int lchild;
int rchild;
}TreeNode;
typedef struct HFTree {
TreeNode* data;
int length;
}HFTree;
HFTree* initTree(int* weight, in
int weight;t length) {
HFTree* T = (HFTree*)malloc(sizeof(HFTree));
T -> data = (TreeNode*)malloc(sizeof(TreeNode) * (2 * length - 1));
T -> length = length;
for (int i = 0; i < length; i++) {
T -> data[i].weight = weight[i];
T -> data[i].parent = 0;
T -> data[i].lchild = -1;
T -> data[i].rchild = -1;
}
return T;
}
int* selectMin(HFTree* T) {
int min = 10000;
int secondMin = 10000;
int minIndex;
int secondIndex;
for (int i = 0; i < T -> length; i++) {
if (T -> data[i].parent == 0) {
if (T -> data[i].weight < min) {
min = T -> data[i].weight;
minIndex = i;
}
}
}
for (int i = 0; i < T -> length; i++) {
if (T -> data[i].parent == 0 && i != minIndex) {
if (T -> data[i].weight < secondMin) {
secondMin = T -> data[i].weight;
secondIndex = i;
}
}
}
int* res = (int*)malloc(sizeof(int)* 2);
res[0] = minIndex;
res[1] = secondIndex;
return res;
}
void createHFTree(HFTree* T) {
int* res;
int min;
int secondMin;
int length = T -> length * 2 - 1;
for (int i = T -> length; i < length; i++) {
res = selectMin(T);
min = res[0];
secondMin = res[1];
T -> data[i].weight = T -> data[min].weight + T -> data[secondMin].weight;
T -> data[i].lchild = min;
T -> data[i].rchild = secondMin;
T -> data[i].parent = 0;
T -> data[min].parent = i;
T -> data[secondMin].parent = i;
T -> length ++;
}
}
void preOrder(HFTree* T, int index) {
if (index != -1) {
printf("%d ", T -> data[index].weight);
preOrder(T, T -> data[index].lchild);
preOrder(T, T -> data[index].rchild);
}
}
int main() {
int weight[7] = {5,1,3,6,11,2,4};
HFTree* T = initTree(weight, 7);
createHFTree(T);
preOrder(T, T -> length - 1);
printf("\n");
return 0;
}
哈夫曼编码
一般左子树为0,右子树为1
c
# 代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 32667
typedef struct hnode{
int l;
int r;
int parent;
int weight;
}Hnode;
typedef struct htree{
Hnode *data;//存放整棵树
int length;
}Hftree;
//初始化哈希树
Hftree * initTree(int weight[],int n)
{
Hftree *T=(Hftree*)malloc(sizeof(Hftree));
T->length=n;//当前结点数量
T->data=(Hnode*)malloc(sizeof(Hnode)*(2*n));//存放二叉树结点数量 2*n
//初始化叶子节点
for(int i=0;i<n;i++)
{
T->data[i].weight=weight[i];
T->data[i].parent=0;//表示父节点不存在
T->data[i].l=-1;
T->data[i].r=-1;
}
return T;
}
//在已经存在的节点中寻找最小权值的两个节点,为他们生成父亲节点
int* Selectmin(Hftree *T)
{
int *res=(int*)malloc(sizeof(int)*2);
int min1=Max,min2=Max;
int m1,m2;
//寻找第一小的节点
for(int i=0;i<T->length;i++)
{
if(T->data[i].parent==0 && T->data[i].weight<min1 )
{
min1=T->data[i].weight;
m1=i;
}
}
//寻找第二小的节点
for(int i=0;i<T->length;i++)
{
if(T->data[i].parent==0 && T->data[i].weight<min2 )
{
if(i!=m1)
{
min2=T->data[i].weight;
m2=i;
}
}
}
//数组存放的是第一小与第二小的权值的下标
res[0]=m1;
res[1]=m2;
return res;
}
void creatTree(Hftree * T)
{
int *res;
int l=T->length *2-1;//二叉树应该有的结点数量 2*n-1(n表示叶子节点的数量)
for(int i=T->length;i<l;i++)//注意i 从T->length开始,前面都是叶子结点
{
res=Selectmin(T);
int m1=res[0];//第一小下标
int m2=res[1];//第二小下标
T->data[m1].parent=i;
T->data[i].l=m1;
T->data[m2].parent=i;
T->data[i].r=m1;
T->data[i].weight=T->data[m1].weight+T->data[m2].weight;
T->data[i].parent=0;
T->length++;//注意现在实际结点长度++
}
}
void Hfcode(Hftree *T,int l)
{
//二维数组,储存哈夫曼编码
char hfcode[6][6];
char s[6]={'A','B','C','D','E','F'};
//实现编码过程
//注意每个叶子结点的编码是由下往上的,所以要倒着存储
//储存单个字母的哈夫曼编码
char code[l];
code[l-1]='\0';
for(int i=0;i<l;i++)
{
int curent=i;
int start=l-1;
int f=T->data[curent].parent;
while(f!=0)
{
--start;
if(T->data[f].l==curent)
{
code[start]='0';
}else{
code[start]='1';
}
//向上遍历
curent=f;
f=T->data[f].parent;
}
//完成一个节点的编码
strcpy(hfcode[i],&code[start]);
}
//输出编码
for(int i=0;i<6;i++)
{
printf("%c:%s\n",s[i],hfcode[i]);
}
}
int main()
{
int weight[6]={15,9,8,12,10,5};
//初始化哈希树
Hftree*T=initTree(weight,6);
//创建哈希树
creatTree(T);
//输出哈希码
Hfcode(T,6);
return 0;
}
图
图的创建与遍历
遍历方法
深度优先搜索----二叉树的前序遍历
1.找一个结点访问
2.找这个结点可以访问的下一个结点继续访问
3.重复以上,直到访问完毕
一条路走到黑,撞南墙才回头,回头后继续走然后撞南墙
广度优先搜索---二叉树的层次遍历
c
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 5
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
typedef struct Queue {
int front;
int rear;
int data[MAXSIZE];
}Queue;
Queue* initQueue() {
Queue* Q = (Queue*)malloc(sizeof(Queue));
Q->front = Q->rear = 0;
return Q;
}
int isFull(Queue* Q) {
if ((Q->rear + 1) % MAXSIZE == Q->front) {
return 1;
}
else {
return 0;
}
}
int isEmpty(Queue* Q) {
if (Q->front == Q->rear) {
return 1;
}
else {
return 0;
}
}
int enQueue(Queue* Q, int data) {
if (isFull(Q)) {
return 0;
}
else {
Q->data[Q->rear] = data;
Q->rear = (Q->rear + 1) % MAXSIZE;
return 1;
}
}
int deQueue(Queue* Q) {
if(isEmpty(Q)) {
return -1;
}
else {
int data = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXSIZE;
return data;
}
}
Graph* initGraph(int vexNum) {
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (int i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs) {
for (int i = 0 ; i < G -> vexNum; i++) {
G -> vexs[i] = vexs[i];
for (int j = 0; j < G -> vexNum; j++) {
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] != 0)
G -> arcNum ++;
}
}
G -> arcNum /= 2;
}
void DFS(Graph* G, int* visited, int index) {
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
for (int i = 0; i < G ->vexNum; i++) {
if (G -> arcs[index][i] == 1 && !visited[i]) {
DFS(G, visited, i);
}
}
}
void BFS(Graph* G, int* visited, int index) {
Queue* Q = initQueue();
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
enQueue(Q, index);
while (!isEmpty(Q)) {
int i = deQueue(Q);
for (int j = 0; j < G -> vexNum; j++) {
if (G -> arcs[i][j] == 1 && !visited[j]) {
printf("%c\t", G -> vexs[j]);
visited[j] = 1;
enQueue(Q, j);
}
}
}
}
int main() {
Graph* G = initGraph(5);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
int arcs[5][5] = {
0,1,1,1,0,
1,0,1,1,1,
1,1,0,0,0,
1,1,0,0,1,
0,1,0,1,0
};
createGraph(G, "ABCDE", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
BFS(G, visited, 0);
printf("\n");
return 0;
}
最小生成树
primer算法
定下顶点,在顶点的边中选取一个最小的边
邻接矩阵的值 ---权值
- 图顶点之前不通,那么邻接矩阵的值为MAX
- 如果顶点是自己本身,那么值为0
c
#include <stdio.h>
#include <stdlib.h>
#define MAX 32767
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
//矩阵中记录每一行的值,且记录起始结点
typedef struct Edge {
char vex;//记录最小边的起始结点
int weight;//记录权值
}Edge;
/**
* 当edge.weight = 0时,代表顶点加入到U集合中
*/
Edge* initEdeg(Graph* G, int index) {
Edge* edge = (Edge*)malloc(sizeof(Edge) * G -> vexNum);
for (int i = 0; i < G ->vexNum; i++) {
edge[i].vex = G -> vexs[index];
edge[i].weight = G -> arcs[index][i];
}
return edge;
}
int getMinEdge(Edge* edge, Graph* G) {
int index;
int min = MAX;
for (int i = 0; i < G -> vexNum; i++) {
if (edge[i].weight != 0 && min > edge[i].weight) {
min = edge[i].weight;
index = i;
}
}
return index;
}
void prim(Graph* G, int index) {
int min;
Edge* edge = initEdeg(G, index);
for (int i = 0; i < G -> vexNum - 1; i++) {
min = getMinEdge(edge, G);
printf("v%c --> v%c, weight = %d\n", edge[min].vex, G -> vexs[min], edge[min].weight);
edge[min].weight = 0;
for (int j = 0; j < G -> vexNum; j++) {
if (G -> arcs[min][j] < edge[j].weight) {
edge[j].weight = G -> arcs[min][j];
edge[j].vex = G -> vexs[min];
}
}
}
}
Graph* initGraph(int vexNum) {
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (int i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs) {
for (int i = 0 ; i < G -> vexNum; i++) {
G -> vexs[i] = vexs[i];
for (int j = 0; j < G -> vexNum; j++) {
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] != 0 && G -> arcs[i][j] != MAX)
G -> arcNum ++;
}
}
G -> arcNum /= 2;
}
void DFS(Graph* G, int* visited, int index) {
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
for (int i = 0; i < G ->vexNum; i++) {
if (G -> arcs[index][i] > 0 && G -> arcs[index][i] != MAX && !visited[i]) {
DFS(G, visited, i);
}
}
}
int main() {
Graph* G = initGraph(6);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
int arcs[6][6] = {
0, 6, 1, 5, MAX, MAX,
6, 0, 5, MAX, 3, MAX,
1, 5, 0, 5, 6, 4,
5, MAX, 5, 0, MAX, 2,
MAX, 3, 6, MAX, 0, 6,
MAX, MAX, 4, 2, 6, 0
};
createGraph(G, "123456", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
prim(G, 0);
return 0;
}
Kruskal算法
首先找到最小的边
c
#include <stdio.h>
#include <stdlib.h>
#define MAX 32767
//图结构定义
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
typedef struct Edge {
int start;
int end;
int weight;
}Edge;
Edge* initEdge(Graph* G) {
int index = 0;
Edge* edge = (Edge*)malloc(sizeof(Edge) * G -> arcNum);
for (int i = 0; i < G -> vexNum; i++) {
for (int j = i + 1; j < G -> vexNum; j++) {
if (G -> arcs[i][j] != MAX) {
edge[index].start = i;
edge[index].end = j;
edge[index].weight = G -> arcs[i][j];
index++;
}
}
}
return edge;
}
void sortEdge(Edge* edge, Graph* G) {
Edge temp;
for (int i = 0; i < G -> arcNum - 1; i++) {
for (int j = 0; j < G -> arcNum - i - 1; j++) {
if (edge[j].weight > edge[j + 1].weight) {
temp = edge[j];
edge[j] = edge[j + 1];
edge[j + 1] = temp;
}
}
}
}
void kruskal(Graph* G) {
int* connected = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0 ; i < G -> vexNum; i++) {
connected[i] = i;
}
Edge* edge = initEdge(G);
//由小到大排列
sortEdge(edge, G);
for (int i = 0; i < G -> arcNum; i++) {
int start = connected[edge[i].start];
int end = connected[edge[i].end];
if (start != end) {
printf("v%c --> v%c weight = %d\n", G -> vexs[edge[i].start], G -> vexs[edge[i].end], edge[i].weight);
for (int j = 0; j < G -> vexNum; j++) {
if (connected[j] == end) {
connected[j] = start;
}
}
}
}
}
//初始化图
Graph* initGraph(int vexNum) {
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (int i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs) {
for (int i = 0 ; i < G -> vexNum; i++) {
G -> vexs[i] = vexs[i];
for (int j = 0; j < G -> vexNum; j++) {
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] != 0 && G -> arcs[i][j] != MAX)
G -> arcNum ++;
}
}
G -> arcNum /= 2;
}
void DFS(Graph* G, int* visited, int index) {
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
for (int i = 0; i < G ->vexNum; i++) {
if (G -> arcs[index][i] > 0 && G -> arcs[index][i] != MAX && !visited[i]) {
DFS(G, visited, i);
}
}
}
int main() {
Graph* G = initGraph(6);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
int arcs[6][6] = {
0, 6, 1, 5, MAX, MAX,
6, 0, 5, MAX, 3, MAX,
1, 5, 0, 5, 6, 4,
5, MAX, 5, 0, MAX, 2,
MAX, 3, 6, MAX, 0, 6,
MAX, MAX, 4, 2, 6, 0
};
createGraph(G, "123456", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
kruskal(G);
return 0;
}
最短路径
floyd算法
c
#include <stdio.h>
#include <stdlib.h>
#define MAX 32767
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
Graph* initGraph(int vexNum) {
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (int i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs) {
for (int i = 0 ; i < G -> vexNum; i++) {
G -> vexs[i] = vexs[i];
for (int j = 0; j < G -> vexNum; j++) {
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] != 0 && G -> arcs[i][j] != MAX)
G -> arcNum ++;
}
}
G -> arcNum /= 2;
}
void DFS(Graph* G, int* visited, int index) {
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
for (int i = 0; i < G ->vexNum; i++) {
if (G -> arcs[index][i] > 0 && G -> arcs[index][i] != MAX && !visited[i]) {
DFS(G, visited, i);
}
}
}
void floyd(Graph* G) {
int d[G -> vexNum][G -> vexNum];
int p[G -> vexNum][G -> vexNum];
for (int i = 0; i < G -> vexNum; i++) {
for (int j = 0; j < G -> vexNum; j++) {
d[i][j] = G -> arcs[i][j];
if (G -> arcs[i][j] > 0 && G -> arcs[i][j] != MAX) {
p[i][j] = i;
}
else
p[i][j] = -1;
}
}
for (int i = 0; i < G -> vexNum; i++) {
for (int j = 0; j < G -> vexNum; j++) {
for (int k = 0; k < G -> vexNum; k++) {
if (d[j][i] + d[i][k] < d[j][k]) {
d[j][k] = d[j][i] + d[i][k];
p[j][k] = p[i][k];
}
}
}
}
for (int i = 0; i < G -> vexNum; i++) {
for (int j = 0; j < G -> vexNum; j++) {
printf("%d ", d[i][j]);
}
printf("\n");
}
printf("\n");
for (int i = 0; i < G -> vexNum; i++) {
for (int j = 0; j < G -> vexNum; j++) {
printf("%d ", p[i][j]);
}
printf("\n");
}
}
int main() {
Graph* G = initGraph(4);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
int arcs[4][4] = {
0, 1, MAX, 3,
1, 0, 2, 2,
MAX, 2, 0, 8,
3, 2, 8, 0
};
createGraph(G, "1234", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
floyd(G);
return 0;
}
dijiaskra算法
三个数组
S数组:记录目标顶点到其他顶点的最短距离是否求得
p数组:记录目标顶点到其他顶点最短路径的前驱结点
D数组:记录目标顶点到其他顶点的最短路径长度
c
#include <stdio.h>
#include <stdlib.h>
#define MAX 32767
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
Graph* initGraph(int vexNum) {
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (int i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs) {
for (int i = 0 ; i < G -> vexNum; i++) {
G -> vexs[i] = vexs[i];
for (int j = 0; j < G -> vexNum; j++) {
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] != 0 && G -> arcs[i][j] != MAX)
G -> arcNum ++;
}
}
G -> arcNum /= 2;
}
void DFS(Graph* G, int* visited, int index) {
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
for (int i = 0; i < G ->vexNum; i++) {
if (G -> arcs[index][i] > 0 && G -> arcs[index][i] != MAX && !visited[i]) {
DFS(G, visited, i);
}
}
}
int getMin(int* d, int* s, Graph* G) {
int min = MAX;
int index;
for (int i = 0; i < G -> vexNum; i++) {
if (!s[i] && d[i] < min) {
min = d[i];
index = i;
}
}
return index;
}
void dijkstra(Graph* G, int index) {
// 准备辅助数组
int* s = (int*)malloc(sizeof(int) * G -> vexNum);
int* p = (int*)malloc(sizeof(int) * G -> vexNum);
int* d = (int*)malloc(sizeof(int) * G -> vexNum);
// 初始化辅助数组
for (int i = 0; i < G -> vexNum; i++) {
if (G -> arcs[index][i] > 0 && G -> arcs[index][i] != MAX) {
d[i] = G -> arcs[index][i];
p[i] = index;
}
else {
d[i] = MAX;
p[i] = -1;
}
if (i == index) {
s[i] = 1;
d[i] = 0;
}
else
s[i] = 0;
}
for (int i = 0; i < G -> vexNum - 1; i++) {
int index = getMin(d, s, G);
s[index] = 1;
for (int j = 0; j < G -> vexNum; j++) {
if (!s[j] && d[index] + G -> arcs[index][j] < d[j]) {
d[j] = d[index] + G -> arcs[index][j];
p[j] = index;
}
}
}
for (int i = 0; i < G ->vexNum; i++) {
printf("%d %d %d\n", s[i], p[i], d[i]);
}
}
int main() {
Graph* G = initGraph(7);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
int arcs[7][7] = {
0, 12, MAX, MAX, MAX, 16, 14,
12, 0, 10, MAX, MAX, 7, MAX,
MAX, 10, 0, 3, 5, 6, MAX,
MAX, MAX, 3, 0, 4, MAX, MAX,
MAX, MAX, 5, 4, 0, 2, 8,
16, 7, 6, MAX, 2, 0, 9,
14, MAX, MAX, MAX, 8, 9, 0
};
createGraph(G, "1234567", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
dijkstra(G, 0);
return 0;
}
拓扑排序
c
#include <stdio.h>
#include <stdlib.h>
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
typedef struct Node {
int data;
struct Node* next;
}Node;
Node* initStack() {
Node* stack = (Node*)malloc(sizeof(Node));
stack -> data = 0;
stack -> next = NULL;
return stack;
}
int isEmpty(Node* stack) {
if (stack -> next == NULL) {
return 1;
}
else {
return 0;
}
}
void push(Node* stack, int data) {
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = stack -> next;
stack -> next = node;
stack -> data ++;
}
int pop(Node* stack) {
if (!isEmpty(stack)) {
Node* node = stack -> next;
stack -> next = node -> next;
return node -> data;
}
else {
return -1;
}
}
int* findInDegrees(Graph* G) {
int* inDegrees = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++) {
inDegrees[i] = 0;
}
for (int i = 0 ; i < G -> vexNum; i++) {
for (int j = 0; j < G -> vexNum; j++) {
if (G -> arcs[i][j])
inDegrees[j] = inDegrees[j] + 1;
}
}
return inDegrees;
}
void topologicalSort(Graph* G) {
int index = 0;
int* top = (int*)malloc(sizeof(int) * G -> vexNum);
int* inDegrees = findInDegrees(G);
Node* stack = initStack();
for (int i = 0 ; i < G -> vexNum; i++) {
if (inDegrees[i] == 0) {
push(stack, i);
}
}
while (!isEmpty(stack)) {
int vex = pop(stack);
top[index++] = vex;
for (int i = 0 ; i < G -> vexNum; i++) {
if (G -> arcs[vex][i]) {
inDegrees[i] = inDegrees[i] - 1;
if (inDegrees[i] == 0)
push(stack, i);
}
}
}
for (int i = 0; i < index; i++) {
printf("%c ", G -> vexs[top[i]]);
}
printf("\n");
}
Graph* initGraph(int vexNum) {
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (int i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs) {
for (int i = 0 ; i < G -> vexNum; i++) {
G -> vexs[i] = vexs[i];
for (int j = 0; j < G -> vexNum; j++) {
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] != 0)
G -> arcNum ++;
}
}
G -> arcNum /= 2;
}
void DFS(Graph* G, int* visited, int index) {
printf("%c\t", G -> vexs[index]);
visited[index] = 1;
for (int i = 0; i < G ->vexNum; i++) {
if (G -> arcs[index][i] == 1 && !visited[i]) {
DFS(G, visited, i);
}
}
}
int main() {
Graph* G = initGraph(6);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
int arcs[6][6] = {
0,1,1,1,0,0,
0,0,0,0,0,0,
0,1,0,0,1,0,
0,0,0,0,1,0,
0,0,0,0,0,0,
0,0,0,1,1,0
};
createGraph(G, "123456", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
topologicalSort(G);
return 0;
}
关键路径
c
#include <stdio.h>
#include <stdlib.h>
#define MAX 65535
typedef struct Graph {
char* vexs;
int** arcs;
int vexNum;
int arcNum;
}Graph;
typedef struct Node {
int data;
struct Node* next;
}Node;
Node* initStack() {
Node* stack = (Node*)malloc(sizeof(Node));
stack -> data = 0;
stack -> next = NULL;
return stack;
}
int isEmpty(Node* stack) {
if (stack -> next == NULL) {
return 1;
}
else {
return 0;
}
}
void push(Node* stack, int data) {
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = stack -> next;
stack -> next = node;
stack -> data ++;
}
int pop(Node* stack) {
if (!isEmpty(stack)) {
Node* node = stack -> next;
stack -> next = node -> next;
return node -> data;
}
else {
return -1;
}
}
int* findInDegrees(Graph* G) {
int* inDegrees = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++) {
inDegrees[i] = 0;
}
for (int i = 0 ; i < G -> vexNum; i++) {
for (int j = 0; j < G -> vexNum; j++) {
if (G -> arcs[i][j] > 0 && G -> arcs[i][j] != MAX)
inDegrees[j] = inDegrees[j] + 1;
}
}
return inDegrees;
}
int* topologicalSort(Graph* G) {
int index = 0;
int* top = (int*)malloc(sizeof(int) * G -> vexNum);
int* inDegrees = findInDegrees(G);
Node* stack = initStack();
for (int i = 0 ; i < G -> vexNum; i++) {
if (inDegrees[i] == 0) {
push(stack, i);
}
}
while (!isEmpty(stack)) {
int vex = pop(stack);
top[index++] = vex;
for (int i = 0 ; i < G -> vexNum; i++) {
if (G -> arcs[vex][i] > 0 && G -> arcs[vex][i] != MAX) {
inDegrees[i] = inDegrees[i] - 1;
if (inDegrees[i] == 0)
push(stack, i);
}
}
}
for (int i = 0; i < index; i++) {
printf("%c ", G -> vexs[top[i]]);
}
printf("\n");
return top;
}
Graph* initGraph(int vexNum) {
Graph* G = (Graph*)malloc(sizeof(Graph));
G -> vexs = (char*)malloc(sizeof(char) * vexNum);
G -> arcs = (int**)malloc(sizeof(int*) * vexNum);
for (int i = 0 ; i < vexNum; i++) {
G -> arcs[i] = (int*)malloc(sizeof(int) * vexNum);
}
G -> vexNum = vexNum;
G -> arcNum = 0;
return G;
}
void createGraph(Graph* G, char* vexs, int* arcs) {
for (int i = 0 ; i < G -> vexNum; i++) {
G -> vexs[i] = vexs[i];
for (int j = 0; j < G -> vexNum; j++) {
G -> arcs[i][j] = *(arcs + i * G -> vexNum + j);
if (G -> arcs[i][j] > 0 && G -> arcs[i][j] != MAX)
G -> arcNum ++;
}
}
}
void DFS(Graph* G, int* visited, int index) {
printf("%c ", G -> vexs[index]);
visited[index] = 1;
for (int i = 0; i < G ->vexNum; i++) {
if (G -> arcs[index][i] > 0 && G -> arcs[index][i] != MAX && !visited[i]) {
DFS(G, visited, i);
}
}
}
int getIndex(int* top, Graph* G, int i) {
int j;
for(j = 0; j < G -> vexNum; j++) {
if (top[j] == i) {
break;
}
}
return j;
}
void criticalPath(Graph* G) {
int* top = topologicalSort(G);
int* early = (int*)malloc(sizeof(int) * G -> vexNum);
int* late = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++) {
early[i] = 0;
late[i] = 0;
}
// 计算最早发生时间
for (int i = 0; i < G -> vexNum; i++) {
int max = 0;
for (int j = 0; j < G -> vexNum; j++) {
if (G -> arcs[j][top[i]] > 0 && G -> arcs[j][top[i]] != MAX) {
int index = getIndex(top, G, j);
if (early[index] + G -> arcs[j][top[i]] > max)
max = early[index] + G -> arcs[j][top[i]];
}
}
early[i] = max;
}
for (int i = 0; i < G -> vexNum; i++) {
printf("%d ", early[i]);
}
printf("\n");
late[(G -> vexNum) - 1] = early[(G -> vexNum) - 1];
// 计算最晚发生时间
for (int i = (G -> vexNum) - 2; i >= 0; i--) {
int min = MAX;
for (int j = 0; j < G -> vexNum; j++) {
if (G -> arcs[top[i]][j] > 0 && G -> arcs[top[i]][j] != MAX) {
int index = getIndex(top, G, j);
if (late[index] - G -> arcs[top[i]][j] < min)
min = late[index] - G -> arcs[top[i]][j];
}
}
late[i] = min;
}
for (int i = 0; i < G -> vexNum; i++) {
printf("%d ", late[i]);
}
printf("\n");
for (int i = 0; i < G -> vexNum; i++) {
for(int j = 0; j < G -> vexNum; j++) {
if (G -> arcs[i][j] > 0 && G -> arcs[i][j] != MAX) {
int start = getIndex(top, G, i);
int end = getIndex(top, G, j);
if ((late[end] - G -> arcs[i][j]) - early[start] == 0) {
printf("start = %d end = %d\n", i, j);
}
}
}
}
}
int main() {
Graph* G = initGraph(9);
int* visited = (int*)malloc(sizeof(int) * G -> vexNum);
for (int i = 0; i < G -> vexNum; i++)
visited[i] = 0;
int arcs[9][9] = {
0, 6, 4, 5, MAX, MAX, MAX, MAX, MAX,
MAX, 0, MAX, MAX, 1, MAX, MAX, MAX, MAX,
MAX, MAX, 0, MAX, 1, MAX, MAX, MAX, MAX,
MAX, MAX, MAX, 0, MAX, 2, MAX, MAX, MAX,
MAX, MAX, MAX, MAX, 0, MAX, 9, 7, MAX,
MAX, MAX, MAX, MAX, MAX, 0, MAX, 4, MAX,
MAX, MAX, MAX, MAX, MAX, MAX, 0, MAX, 2,
MAX, MAX, MAX, MAX, MAX, MAX, MAX, 0, 4,
MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX, 0
};
createGraph(G, "012345678", (int*)arcs);
DFS(G, visited, 0);
printf("\n");
criticalPath(G);
return 0;
}