链式存储结构二叉树
typedef struct node {
int data;
struct node *lchild, *rchild;
}bitree;
void swap(bitree *T)
链表
typedef struct node {
int data;
struct node* next;
}Node, *LinkList;
p = (LinkList)malloc(sizeof(Node));
LinkList addin(LinkList A)
顺序表
struct record {
int key;
int others;
};
int bisearch(struct record r[], int k) {
r[mid].key == k;
}
栈
//顺序栈
typedef struct {
int data[MAXSIZE];
int top;
}SeqStack;
//链栈
typedef struct Snode {
int data;
struct Snode *next;
}*LinkStack;
1.在单链表中删除值相同的多余结点的算法
LinkList p, q, s;
for(p = T; p != NULL; p = p->next) {
for(q = p->next, s = q; q != NULL) {
if(p->data == q->data ){
s->next = q->next;
free(q);
q = s->next;
}
else {
s = q;
q = q->next;
}
}
}
}
2.在链式存储结构上建立一棵二叉排序树
void bstinsert(bitree *&bt, int key) {
if(bt == NULL) {
bt = (bitree*)malloc(sizeof(bitree));
bt->key = key;
bt->lchild = bt->rchild = NULL;
}
else if(bt->key > key) bstinsert(bt->lchild, key);
else bstinsert(bt->rchild, key);
}
void createbsttree(bitree *bt) {
int i;
for(i = 1; i <= n ; i++)bstinsert(bt, random(100));
}
3.判断两个二叉树是否相同
void createbsttree(bitree *bt) {
int i;
for(i = 1; i <= n ; i++)bstinsert(bt, random(100));
}
int judgebitree(bitree *bt1, bitree *bt2) {
if(bt1 == NULL && bt2 == NULL)return 1;
else if(bt1 == NULL || bt2 == NULL || bt1->data != bt2->data)return 0;
else return(judgebitree(bt1->lchild, bt2->lchild) * judgebitree(bt1->rchild, bt2->rchild))
}
4.两个单链表合并
void mergelklist(LinkList ha, LinkList hb, LinkList &hc) {
LinkList s = hc = NULL;
if(ha != NULL && hb != NULL) {
if(ha->data < hb->data) {
if(s == NULL) {
hc = s = ha;
}
else {
s->next = ha;
s = ha;
}
ha = ha->next;
}
else {
if(s == NULL) {
hc = s = hb;
}
else {
s->next = hb;
s = hb;
}
hb = hb->next;
}
}
if(ha == NULL) s->next = hb;
else s->next = ha;
}
5.判断二叉树是否为二叉排序树
void inorder(bitree *bt) {
if(bt != NULL) {
inorder(bt->lchild);
if(minnum > bt->key) flag = 0;
//若当前节点的值小于之前遍历到的最小值 minnum,则将 flag 设置为 0,表示该二叉树不是按照升序排列的
minnum = bt->key;//更新 minnum 的值为当前节点的值
inorder(bt->rchild);
}
}
6.在链式结构上实现简单选择排序算法
void simple(LinkList &h) {
LinkList p, q, s;
int min, t;
if(h == NULL || h->next == NULL) return;
for(q = h, q != NULL;q = q->next ) {
min = q->data;
s = q;
for(p = q->next; p != NULL; p = p->next) {
if(min > p->data){
min = p->data;
s = p;
}
if(s != q) {
t = s->data;
s->data = q->data;
q->data = t;
}
}
}
}
7.求结点在二叉排序树中层次
void level(bitree *bt, int x) {
int lev = 0;
if(bt != NULL) {
lev++;
if(bt->key == x)return;
else if(bt->key > x) level(bt->lchild, x);
else level(bt->rchild, x);
}
}
8.将所有奇数移到所有偶数之前
void quickpass(int r[], int s, int t) {
//对r[]数组中从索引s到索引t的元素进行排序
int i = s, j = t, x = r[s];
while(i < j) {
while(i < j && r[j]%2 == 0) j = j-1;
if(i < j){
r[i] = r[j];
i = i+1;
}
while(i < j && r[i]%2 == 1) i = i+1;
if(i < j) {
r[j] = r[i];
j = j-1;
}
}
r[i] = x;
}
9.计判断单链表中元素是否是递增
int inser(LinkList h) {
if(h == NULL || h->next == NULL) return 1;
for(q = h, p = h->next; q != NULL; q = p, p = p->next) {
if(q->data > p->data) return 0;
}
return 1;
}
10.计在二叉排序树上查找结点 X
bitree *bstsearch(bitree *t, int key) {
bitree *p = t;
while(p != 0){
if(p->data == key) return p;
else if(p->key > key) p = p->lchild;
else p = p->rchild;
}
return 0;
}
11.顺序表删除第i个元素
int DeleteList(SqList& L, int i) {
int j;
if (i < 1 || i > L.length) {
printf("不存在第i个元素");
return 0;//要删除的元素不存在
}
for (j = i + 1; j < L.length + 1; j++) {
L.elem[j - 2] = L.elem[j - 1];//将ai+1~an顺序上移,从而删除ai,注意第i个元素是a[i-1]
}
L.length--;//修改表长
return 1;//删除成功
}
12.二叉树层次遍历
#define MAX 100
void ss(BiTree T) {
BiTree Q[MAX], p;
int f = 0, r = 0;//首尾指针
if(T == NULL) return;
Q[r++] = T;
while(f != r) {
p = Q[f++];
printf("%c", p->data);
if(p->lchild) {
if(r >= MAX) {
printf("overflow");
exit(0);
}
Q[r++] = p->lchild;
}
if(p->rchild) {
if(r >= MAX) {
printf("overflow");
exit(0);
}
Q[r++] = p->rchild;
}
}
}
//这种算法会导致假溢出,所以接下来用循环队列
#define MAX 1000
//二叉链表
typedef struct BiTNode {
int data;
struct BiTNode *lchild, rchild;//左右子树根结点地址
}BiTNode, *BiTree;
//顺序栈
typedef struct {
BiTree data[MAX];
int top;
}SeqStack;
//先序非递归遍历二叉树
//访问根结点后,在访问左子树前,应保存其非空右子树
void PreorderTraverse(BiTree T) {
SeqStack s;
s.top = -1;
BiTree p = (BiTNode*)malloc(sizeof(BiTNode));
//也可以用BiTree p = (BiTree)malloc(sizeof(BiTNode));
p = T;
while(p) {
printf("%c", p->data);//访问p结点
if(p->rchild) {//若p有右孩子
if(s.top == MAX-1) exit(0);//栈满了,错误
else s.data[++s.top] = p->rchild;//栈没满,则右孩子入栈
p = p->lchild;//访问p的左孩子
}
//下一轮,若p的左孩子为空,则不再进行while,访问栈顶元素,相当于回溯
if(s.top != -1) p = s.data[s.top--];//若栈不空,则栈顶元素出栈
}
}
//中序非递归遍历二叉树
//访问根结点的左子树前,应保存其根结点,以便访问根和根的右子树
void InorderTraverse(BiTree T) {
SeqStack s;
s.top = -1;
BiTree p = (BiTNode*)malloc(sizeof(BiTNode));
p = T;
while(p || (s.top != MAX - 1)) {
while(p) {
if(s.top == MAX-1) exit(0);//栈满了,错误
s.data[++s.top] = p;//栈没满,则p入栈
p = p->lchild;//访问p的左孩子
}
if(s.top != -1) {
p = s.data[s.top--];//若栈不空,则栈顶元素出栈
printf("%c", p->data);//访问p结点
p = p->rchild;
}
}
//后序非递归遍历二叉树
//访问根结点的左子树前,应保存其根结点,以便访问根的右子树和根
void InorderTraverse(BiTree T) {
SeqStack s;
s.top = -1;
BiTree p = (BiTNode*)malloc(sizeof(BiTNode));
p = T;
while(p || (s.top != MAX - 1)) {
while(p) {
if(s.top == MAX-1) exit(0);//栈满了,错误
s.data[++s.top] = p;//栈没满,则p入栈
p = p->lchild;//访问p的左孩子
}
if(s.top != -1) {
p = s.data[s.top--];//若栈不空,则栈顶元素出栈
printf("%c", p->data);//访问p结点
p = p->rchild;
}
}
深搜
//图的邻接表存储
typedef struct ArcNode {
int vex;//该弧所指向的顶点的位置
struct ArcNode *link;//指向下一条弧的指针
InfoType *info;//该弧的相关信息的指针
}ArcNode;//单链表节点类型
typedef struct VNode {
int data;//顶点信息
ArcNode *firstarc;//指向第一条依附该顶点的弧
}VNode;//数组元素类型
typedef struct {
VNode arc[MAXSIZE];
int vexnum, arcnum;//顶点数,边数
int kind;//图的类型,有向or无向
}Graphs;
void DFSTraverse(Graphs G) {
//对图G作深度优先遍历
for(v = 0; v < G.vexnum; ++v)
visited[v] = 0;//访问标志数组初始化,0代表未被访问
for(v = 0; v < G.vexnum; ++v)
if(!visited[v]) DFS(G,v);//对未访问的顶点调用DFS
}
void DFS(Graphs G, int v) {
printf("%d\t", v);
visited[v] = 1;
p = G.arc[v].firstarc;
while(p) {
w = p->vex;
if(visited[w] == 0) DFS(G, w);
p = p->link;
}
}
宽搜
void BFSTraverse(Graphs G) {
//对图G作广度优先遍历
for(v = 0; v < G.vexnum; ++v)
visited[v] = 0;//访问标志数组初始化,0代表未被访问
for(v = 0; v < G.vexnum; ++v)
if(!visited[v]) BFS(G,v);//对未访问的顶点调用BFS
}
void BFS(Graphs G, int v) {
int Q[MAX], f = 0, r = 0;
printf("%d\t", v);
visited[v] = 1;//访问v
Q[r++] = v;//v入队
while(f <r) {//当队列不空时
x = Q[f++]; //队头x出队
p = G.arc[x].firstarc;//x的邻接点p
while(p) {//当p存在时
w = p->vex;//访问x的邻接结点
if(visited[w] == 0) {//若w未访问过
visited[w] = 1;//则访问
printf("%d\t", w);
Q[r++] = w;//并入队
p = p->link;//求下一个邻接点
}
}
}
while(p) {
w = p->vex;
if(visited[w] == 0) DFS(G, w);
p = p->link;
}
}
二叉排序树,查找、插入
//存储结构为二叉链表
typedef struct NODE {
int key;
struct NODE *lc, *rc;
}BiNode, *BiTree;
Bitree Search(BiNode *t, int x) {
BiTree p;
p = t;
while(p != NULL) {
if(x == p->key) return p;//若x等于根结点的关键字,则查找成功
if(x < p->key p = p->lc;//小于则在左子树上找
else p = p->rc;//大于则在右子树找
}
return p;//函数返回查找结果,没找到为空指针!
}
int Insert(Bitree &t, int x) {
BiTree q, p, s;
q = NULL;//q为p的双亲节点,根节点无双亲节点
p = t;//p为正在查看的节点,初始从根节点t开始
while(p != NULL) {
if(x == p->key) return 0;//在当前二叉树中找到x,不用插入
q = p;//更新双亲节点
if(x < p->key) p= p->lc;//如果x比当前节点小,则进入左子树
else p = p->rc; //如果x比当前节点大,则进入右子树
}
s = (BiTree)malloc(sizeof(Binode));//没找到x,做插入,申请节点空间
s->key = x; s->lc = NULL; s->rc = NULL;//s存放x,设为叶节点
if(q == NULL) t = s; //若原先的二叉树是一棵空树,新插入的x对应的节点s为插入后二叉树的根节点
else if(x < q->key) q->lc = s;//若x小于其双亲节点,则作为其左孩子
else q->rc = s;//若x大于其双亲节点,则作为其右孩子
return 1;
}
排序
插入排序
//待排序的数据元素从下标为1的数组元素开始存放。下标0处为哨兵项
void insertSort(SqList L) {
int i, j;
for(i = 2; i <= L.length; i++)//从第二个数据开始插入,n = L.length
if(L.r[i].key < L.r[i-1].key) {//第i个数据比前面已经有序的i-1个数据最大的小
L.r[0] = L.r[i];//将第i个数据放入哨兵位置
L[i] = L.r[i-1];
for(j = i-2; L.r[0].key < L.r[j].key; --j)///L.r[0]存放的是此次要插入的第i个数据
L.r[j+1] = L.r[j];
L.r[j+1] = L.r[0];
}
}
二分插入排序
void BinsertSort(SqList &L) {
int i, low, high, mid;
for(i = 2; i <= L.length; i++)
if(L.r[i].key < L.r[i-1].key) {
L.r[0] = L.r[i];
low = 1;
high = i-1;
while(low <= high) {
mid = (low +high)/2;
if(L.r[0].key < L.r[mid].key)high = mid - 1;
else low = mid +1;
}
for(j = i-1; k >= high + 1; j--)
L.r[j+1] = L.r[j];
L.r[high + 1] = L.r[0];
}
}
快速排序
int partition(SqList L, int l, int h) {
L.r[0] = L.r[l];//取待排序的第一个数据元素为基准放到L.r[0]
//原来的L.r[l]初始相当于空着
//从后面开始找
while(l < h) {//一趟快排结束的条件是左右边界重合
//若右边界大于基准,则右边界左移一位
while((l<h) && (L.r[h].key >= L.r[0].key))
h--;
//右边界小于基准,则把右边的大数放到前面的空位
if(l < h) {
L.r[l] = L. r[h];
l++;
}
//若左边界小于基准,则左边界右移一位
while((l<h) && (L.r[l].key <= L.r[0].key))
l++;
//若大于,则把左边的小数移到后面的空里
if(l < h) {
L.r[h] = L. r[l];
h--;
}
//l=h跳出循环
L.r[l] = L.r[0];//把基准元素放到这个重合处的空里
return l;//返回基准的位置
}
}
//递归,结束的条件是待排序的数据元素个数小于等于1
void QSort(SqList &L. int l, int h) {
int t;
if(l<h) { //待排序的数据有2个或2个以上才进行排序操作
t = partition(L, l, h);//调用一趟快排,t为返回的基准的位置
QSort(L, l, t-1);//对比基准小的子序列继续进行快速排序
QSort(L, t+1, h);//对比基准大的子序列继续进行快速排序
}
}
冒泡排序
void qppx(SqList &L) {
int i, j, k;
j = 1;
k = 1;
//共有n-1趟排序:j从1到length-1
while((j < L.length) && (k > 0)) {
k = 0;
//第j趟要比较n-j次:i从1到n-j
for(i = 1; i <= L.length-j; i++)
if(L.r[i+1].key < L.r[i].key]) {//出现逆序,利用辅助空间r[0]交换
L.r[0] = L.r[i];
L.r[i] = L.r[i+1];
L.r[i+1] = L.r[0];
k++;//k记录每一趟排序中发生的交换次数,交换则+1
}
j++;}
}
简单选择
void SelectSort(SqList &L) {
int i, j, k;
for(i = 1; i < L.length; i++) {//进行n-1趟排序
k = i;//第i趟时,初始设当前最小的数据为第k=i个数据元素
for(j = i+1; j <= L.length; ++j)
//从第i+1个到第n个,依次和当前最小的第k个数据元素比较,若比第k个还小,则更新k
if(L.r[j].key < L.r[k].key)
k = j;//标记j为当前最小的元素
//如果现在最小的元素不是i,就把最小元素交换到i上
if(k != i) {
//交换借用额外的辅助空间L.r[0], O(1)
L.r[0] = L.r[i];
L.r[i] = L.r[k];
L.r[k] = L.r[0];
}
}
}
}
计算有向图的出入度
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
typedef struct ArcNode {
int vex; // 该弧所指向的顶点的位置
struct ArcNode *link; // 指向下一条弧的指针
} ArcNode; // 单链表节点类型
typedef struct VNode {
int data; // 顶点信息
ArcNode *firstarc; // 指向第一条依附该顶点的弧
} VNode; // 数组元素类型
typedef struct {
VNode arc[MAXSIZE];
int vexnum, arcnum; // 顶点数,边数
int kind; // 图的类型,有向or无向
} Graphs;
// 计算顶点的入度和出度
void calcDegree(Graphs *G, int numb, int *in_degree, int *out_degree) {
// 初始化入度和出度
*in_degree = *out_degree = 0;
// 遍历邻接表,计算入度和出度
for (int i = 0; i < G->vexnum; i++) {
ArcNode *p = G->arc[i].firstarc;
while (p) {
if (p->vex == numb) {
// 找到一条以numb为终点的弧,增加入度
(*in_degree)++;
}
p = p->link;
}
if (i == numb) {
// 当前顶点为numb,统计出度
p = G->arc[i].firstarc;
while (p) {
(*out_degree)++;
p = p->link;
}
}
}
}