数据结构算法
南邮数据结构自己整理的基础算法,掺杂了南邮的C语言教材和王道教材
&2 线性表
&2.1 顺序表
顺序存储类型:
#define MaxSize 50 //线性表最大长度
typedef struct {
ElemType data[ MaxSize ]; //创建数据元素数组
int length; //线性表当前长度
} SqList; //线性表静态顺序实现sqlist
动态分配线性表:
#define InitSize 100 //线性表最大长度
typedef struct {
ElemType *data; //指示动态数组的指针
int MaxSize; //数组最大容量
int length; //数组当前长度
} SeqList; //线性表动态顺序实现seqlist
初始化动态分配:
#define error 0
#define ok 1
typedef int Status ; //类型定义
Status Init ( SeqList *L , int size ) { //Init初始化函数,status为整型=int
L -> MaxSize = size; //线性表最大长度
L -> length = 0; //当前长度
L -> data = ( ElemType *) malloc ( sizeof ( ElemType ) * size ); //动态分配数组空间,malloc动态分配函数
if ( !L -> data ) { //动态数组为空执行
return error; //0
}
return ok; //1
}
查找(按位查找):
Status Find ( SeqList L , int i , ElemType *x) { //按位查找函数
if ( i < 0 || i > L -> length - 1 ) { //越界判断
return error;
}
*x = L -> data[ i ]; //取出data[i]通过参数x返回
return ok;
}
查找(按值查找):
int LocateElem ( SeqList L , ElemType e ) { //按值查找函数
int i; //位序
for ( i = 0 ; i < L -> lentgh ; i++ ) { //循环查找
if ( L -> data[ i ] == e ) { //判断是否相等
return i + 1; //返回位序
}
}
return 0;
}
插入(在Ai后面插入x):
Status Insert ( SeqList *L , int i , ElemType x ) { //插入函数
int j; //循环下标
if ( i < -1 || i > L -> length -1 ) { //越界判断
return error;
}
if ( L -> length == L -> MaxSize ) { //数组是否满长
return error;
}
for ( j = L -> length - 1 ; j > i ; j-- ) { //从后往前依次将数组元素往后移一位
L->data[ j + 1 ] = L->data[ j ];
}
L -> data[ i + 1 ] = x; //将元素放入后一位位置
L -> length = L -> length + 1; //表长长度+1
return ok;
}
删除(Ai位置删除):
Status Delete ( SeqList *L , int i , ElemType *x ) { //删除函数
int j; //循环下标
if ( i < 0 || i > L -> length - 1 ) { //越界判断
return error;
}
if ( !L -> length ) { //线性表是否为空
return error;
}
e = L -> data[ i ]; //取出data[i]通过参数x返回
for ( j = length + 1 ; j < L -> length ; j++ ) { //从后往前依次将数组元素往前移一位
L -> data[ j - 1 ] = L -> data[ j ];
}
L->length --; //表长长度-1
return ok;
}
输出(顺序表元素依次输出):
Status Output ( SeqList *L ) { //输出顺序表元素
int i; //循环下标
if ( L -> length == 0 ) { //线性表是否为空
return error;
}
for ( i = 0 ; i <= L -> length ; i++ ) { //从前往后数组依次输出
printf( "%d " , L -> data[ i ] );
}
printf( "\n" );
return ok;
}
撤销(释放动态分配空间,防止内存泄漏):
void Destory ( SeqList *L ) {
L -> length = 0;
L -> MaxSize = 0;
free( L -> data );
}
&2.2 链式存储
&2.2.1单链表类型定义
typedef struct node { //单链表结点
ElemType element; //结点数据域
struct node *link; //结点指针域
} Node;
typedef struct singleList { //单链表
Node *first; //头指针
int n; //单链表元素个数
} SingleList;
单链表初始化:
Status Init ( SingleList *L ) {
L -> first = NULL; //第一个结点为空结点
L -> n = 0; //元素个数为0
return ok;
}
头插法建立单链表:
SingleList List_HeadInsert ( SingleList &L ) { //头插法
Node *s;
int x; //数据域
L = ( SingleList ) malloc ( sizeof ( Node ) ); //创建头结点
L -> next = NULL; //指针域为空
scanf( "%d" , &x );
while ( x != 9999 ) { //9999表示结束
s = ( Node* ) malloc ( sizeof ( Node ) ); //创建新结点
s -> element = x; //赋值
s -> next = L -> next; //将原来头结点的指针域赋给插入结点
L -> next = s; //将插入结点作为头结点的指针域
scanf( "%d" , &x );
}
return L;
}
尾插法建立单链表:
SingleList List_TailInsert ( SingleList &L ) {
int x;
L = ( SingleList ) malloc ( sizeof ( Node ) ); //创建头结点
Node *s; //插入结点
Node *r = L; //表尾指针
scanf( "%d" , &x );
while ( x != 9999 ) { //9999表示结束
s = ( Node* ) malloc ( sizeof ( Node ) ); //创建新结点
s -> element = x; //数据域赋值
r -> next = s; //表尾指针结点域赋值
r = s; //表尾指针更换
scanf( "%d" , &x );
}
r -> next = NULL; //表尾指针结点域为NULL
return L;
}
按序号查找(数据域):
Status Find_Element ( SingleList L , int i , ElemType *x ) { //链表,位序,值
Node *p;
int j;
if ( i < 0 || i > L-> n - 1 ) { //越界判断
return error;
}
p = L -> first; //头结点
for ( j = 0 ; j < i ; j++ ) { //遍历到指定位序
p = p -> link;
}
*x = p -> element; //取出指定结点的元素值
return ok;
}
按序号查找(结点):
Node *Find_Node ( SingleList L , int i ) { //链表,位序,值
Node *p;
int j;
if ( i < 0 || i > L-> n - 1 ) { //越界判断
return error;
}
p = L -> first; //头结点
for ( j = 0 ; j < i ; j++ ) { //遍历到指定位序
p = p -> link;
}
//取出指定结点的元素值
return p;
}
按结点值查找:
Node *Locate_Elem ( SingleList L , ElemType e ) { //链表,值
Node *p = L -> first; //头结点
p = p -> link; //第一个结点
while ( p != NULL && p -> element != e ) { //判断空结点和数据域值
p = p -> link;
}
return p;
}
插入(前插在i位置):
p = Find_Node ( L , i - 1 ); //找到插入位置前一个位置
s -> link = p -> link; //结点域赋值
p -> link = s; //结点域赋值
完整插入:
Status Insert ( SingleList *L , int i , ElemType x ) {
Node *p , *q;
int j;
if ( i < -1 || i > L -> n - 1 ) { //越界判断
return error;
}
p = L -> first;
for ( j = 0 ; j < i ; j++ ) { //新结点放后面
p = p -> link;
}
q = ( Node* ) malloc ( sizeof( Node ) ); //生成新结点
q -> element = x;
if ( i > -1 ) {
q -> link = p -> link; //放入后面结点
p -> link = q;
} else {
q -> link = L -> first; //变成头结点
L -> first = q;
}
L -> n ++;
return ok;
}
插入(s插入到p之前):
s -> link = p -> link; //结点域赋值
p -> link = s; //交换位置
temp = p -> element; //交换数据域
p -> element = s -> element;
s -> element = temp;
删除:
p = Find_Node( L , i - 1 ); //找前驱
q = p -> link; //找到被删除结点
p -> link = q -> link; //删除结点域赋值给前驱结点的结点域
free( q ); //释放结点
删除(赋值):
q = p -> link; //找后继结点
p -> element = p -> link -> element; //后继值赋值
p -> link = q -> link; //后继的后继为后继
free( q );
完整删除:
Status Delete ( SingleList *L , int i ) {
int j;
Node *p, *q;
if ( !L -> n ) { //空表判断
return error;
}
if ( i < 0 || i > L -> n - 1 ) { //月结判断
return error;
}
q = L -> first;
p = L -> first;
for ( j = 0 ; j < i - 1 ; j++ ) {
q = q -> link;
}
if ( i == 0 ) {
L -> first = L -> first -> link; //头结点为头结点的结点域
} else {
p = q -> link; //后继的后继为后继
q -> link = p -> link;
}
free( q );
L -> n--;
return ok;
}
输出:
Status Output( SingleList *L ) {
Node *p;
if ( !L -> n ) { //空表判断
return error;
}
p = L -> first;
while( p ) {
printf( "%d" , p -> element );
p = p -> link;
}
return ok;
}
撤销:
void Destory( SingleList *L ) {
Node *p;
while ( L -> first ) {
p = L -> first -> link; //保存后继
free( L -> first );
L -> first = p;
}
}
&2.2.2带表头结点的单链表
typedef struct headerList { //同SingleList
Node *head;
int n;
} HeaderList;
初始化:
Status Init ( HeaderList *h ) {
h -> head = ( Node* ) malloc ( sizeof( Node ) );
if ( ! h -> head ) {
return error;
}
h -> head -> link = NULL;
h -> n = 0;
return ok;
}
插入:
Status Insert ( HeaderList *h , int i , ElemType x ) {
Node *p, *q;
int j;
if ( i < - 1 || i > h -> n - 1 ) {
return error;
}
p = h -> head;
for ( j = 0 ; j <= i ; j++ ) {
p = p -> link;
}
q = ( Node* ) malloc ( sizeof( Node ) );
q -> element = x;
q -> link = p -> link; //后继为插入的后继
p -> link = q;
h -> n ++;
return ok;
}
删除:
Status Delete ( HeaderList * h , int i ) {
int j;
Node *p, *q;
if ( !h -> n ) {
return error;
}
if ( i < 0 || i > h -> n - 1 ) {
return error;
}
q = h -> head;
for ( j = 0 ; j < i ; j++ ) {
q = q -> link;
}
p = q -> link;
q -> link = p -> link; //后继结点替换
free( p );
h -> n --;
return ok;
}
&2.2.3循环单链表
r -> link = L -> head; //表尾指针的结点域为表头结点
&2.2.4双向链表
typedef struct duNode {
ElemType element;
struct duNode *llink; //左结点
struct duNode *rlink; //右结点
} DuNode , Dulist;
插入:
q -> llink = p -> link; //先把插入的两端赋值
q -> rlink = p;
p -> llink -> rlink = q; //先赋值前端
p -> link = q; //最后赋值两个结点关联的结点域
删除:
p -> llink -> rlink = p -> rlink; //左右结点直接赋值
p -> rlink -> llink = p -> llink;
free( p );
&2.2.5循环双链表
p -> llink = L -> head; //p为尾结点
L -> head -> llink = L; //空表
L -> head -> rlink = L;
&2.2.6静态链表
#define MaxSize 50
typedef struct {
ElemType data; //存储数据元素
int next; //结点域为数组下标
} SLinkList[ MaxSize ];
&2.2.7线性表应用
多项式类型定义:
typedef struct pNode {
int coef;
int exp;
struct pNode* link;
} PNode;
typedef struct polunominal {
PNode *head;
} Polynominal;
多项式创建:
void Create ( Polynominal *p ) {
PNode *pn, *pre, *q; //插入结点,前驱结点,后继结点
p -> head = ( PNode* ) malloc ( sizeof( PNode ) );
p -> head -> exp = - 1;
p -> head -> link = p -> head;
for ( ; ; ) {
pn = ( PNode* ) malloc ( sizeof( PNode ) );
printf( "coef:\n" );
scanf( "%d" , &pn -> coef );
printf( "exp:\n" );
scanf( "%d" , &pn -> exp );
if ( pn -> exp < 0 ) {
break;
}
pre = p -> head;
q = p -> head -> link;
while ( q && q -> exp > pn -> exp ) { //q为小于pn的结点,pre为大于pn的结点
pre = q;
q = q -> link;
}
pn -> link = q;
pre -> link = pn;
}
}
多项式加法:
void Add ( Polynominal *px , Polynominal *qx ) {
PNode *q, *q1 = qx -> head , *p, *p1, *temp;
p = px -> head -> link; //px第一个结点
q = q1 -> link; //q1是q的前驱
while ( p -> exp >= 0 ) {
while ( p -> exp < q -> exp ) { //跳过系数大的项
q1 = q;
q = q -> link;
}
if ( p -> exp == q -> exp ) { //指数相等
q -> coef = q -> coef + p -> coef;
if ( q -> coef == 0 ) { //系数和为0则删除结点
q1 -> link = q -> link;
free( q );
q = q1 -> link;
p = p -> link;
} else { //不为0则不管
q1 = q;
q = q -> link;
p = p -> link;
}
} else { //不存在相对应指数项,插入相关项
temp = ( PNode* ) malloc ( sizeof( PNode ) );
temp -> coef = p -> coef;
temp -> exp = p -> exp;
temp -> link = q1 -> link;
q1 -> link = temp;
q1 = q1 -> link;
p = p -> link;
}
}
}
&3 栈和队列
&3.1 栈
&3.1.1 栈顺序结构实现
typedef struct stack {
int top; //当前栈顶位置下标,初始为-1,栈长为top+1
int maxSize; //maxSize-1为堆栈最大栈顶位置下标
ElemType *element; //存储堆栈元素的一维数组首地址指针
//ElemType data[ maxSize ];
} Stack;
&3.1.2 栈的基本运算
初始化(创建)
void Create ( Stack *s , int mSize ) {
S -> maxSize = mSize;
S -> element = ( ElemType * ) malloc ( sizeof ( ElemType ) * mSize );
S -> top = -1;
}
销毁栈,释放数组空间:
void Destroy ( Stack *S ) {
S -> maxSize = 0;
free( S -> element );
S -> top = -1;
}
判断空栈:
bool IsEmpty ( Stack *S ) {
return S -> top == -1;
}
判断栈满:
bool IsFull ( Stack *S ) {
return S -> top == S -> maxSize - 1;
}
获取栈顶元素:
bool Top ( Stack *S , ElemType *x ) {
if ( IsEmpty ( S ) ) {
return false;
}
*x = S -> element [ S -> top ];
return true;
}
入栈操作:
bool Push ( Stack *S , ElemType x ) {
if ( IsFull ( S ) ) {
return false;
}
S -> top ++;
S -> element [ S -> top ] = x;
return true;
}
出栈操作:
bool Pop ( Stack *S ) {
if ( IsEmpty ( S ) ) {
return false;
}
S -> top --;
return true;
}
清除堆栈中所有元素,不释放空间:
void Clear ( Stack *S ) {
S -> top = -1;
}
&3.1.3 栈的链式存储
链式存储类型:
typedef struct Linknode {
ElemType data;
struct Linknode *next;
} *LiStack;
&3.2 队列
&3.2.1 队列顺序表示
typedef struct queue {
int front; //指向队头元素前一个位置
int rear; //指向队尾元素
int maxSize;
ElemType *element;
} Queue;
队空:
Q -> front == Q -> rear;
&3.2.2 循环队列
循环队列结构体定义:
typedef struct queue {
int front;
int rear;
int maxSize;
ElemType *element;
} Queue;
创建空队列:
void create( Queue *Q , int mSize ) {
Q -> maxSize = mSize;
Q -> element = ( ElemType *) malloc ( sizeof( ElemType) * mSize );
Q -> front = Q -> rear = 0;
}
销毁队列,释放空间:
void Destory( Queue *Q ) {
Q -> maxSize = 0;
free( Q -> element );
Q -> front = Q -> rear = -1;
}
判断队列是否为空:
bool IsEmpty( Queue *Q ) {
return Q -> front == Q -> rear;
}
判断队列是否满:
bool IsFull( Queue *Q ) {
return ( Q -> rear + 1 ) % Q -> maxSize = Q -> front;
}
获取队头元素:
bool Front( Queue *Q , ElemType *x ) {
if( IsEmpty( Q ) ) {
return false;
}
*x = Q -> element[ ( Q -> front + 1 ) % Q -> maxSize ];
return true;
}
队尾插入元素(入队):
bool EnQueue( Queue *Q , ElemType x ) {
if( IsFull( Q ) ) {
return false;
}
Q -> rear = ( Q -> rear + 1 ) % Q -> maxSize;
Q -> element[ Q -> rear ] = x;
return true;
}
删除队头元素(出队):
bool DeQueue( Queue *Q ) {
if( IsEmpty( Q ) ) {
return false;
}
Q ->front = ( Q -> front + 1 ) % Q -> maxSize;
return true;
}
清除队列中全部元素,不释放空间:
void Clear( Queue *Q ) {
Q -> front = Q -> rear = 0;
}
队列判断条件:
( Q -> rear + 1 ) % Q -> maxSize = Q -> front; //队满条件
Q -> front == Q -> rear; //队空条件
( Q -> rear - Q -> front + maxSize ) % maxSize; //元素个数
&3.2.3 链式队列
链式存储类型定义:
typedef struct {
ElemType data;
struct LinkNode *next;
} LinkNode;
typedef struct {
LinkNode *front , *rear;
}
链式队列判断条件:
Q -> front == Q -> rear == NULL;
初始化:
void InitQueue( LinkQueue &Q ) {
Q -> front = Q -> rear = ( LinkNode *) malloc ( sizeof( LinkNode ) );
Q -> front -> next = NULL;
}
判队空:
bool IsEmpty( LinkQueue Q ) {
if( Q -> front == Q -> rear ) {
return true;
} else {
return false;
}
}
入队:
void EnQueue( LinkQueue &Q , ElemType x ) {
LinkNode *s = ( LinkNode *) malloc ( sizeof( LinkNode ) );
s -> data = x;
s -> next = NULL;
Q -> rear -> next = s;
Q -> rear = s;
}
出队:
bool DeQueue( LinkQueue &Q , ElemType &x ) {
if( Q -> front == Q -> rear ) {
return false;
}
LinkNode *p = Q -> front -> next;
if( Q -> rear == p ) {
Q -> rear = Q -> front;
}
free( p );
return true;
}
&4 数组和字符串
&4.1 稀疏矩阵
&4.1.1 定义
#define maxsize 100
typedef int ElemType;
typedef struct term {
int col , row;
ElemType value;
} Term;
typedef struct sparsematrix {
int m , n , t;
Term table[ maxSize ];
} SparseMatrix;
&4.1.2 快速转置
for( int j = 0 ; j < n ; j++ ) {
num[ j ] = 0;
}
for( int i = 0 ; i < t ; i++ ) {
num[ A.table[ i ].col ]++;
}
for( int j = 0 ; j < n ; j++ ) {
k[ j ] = 0;
}
for( int j = 1 ; j < n ; j++ ) {
k[ j ] = k[ j - 1 ] + num[ j - 1 ];
}
for( int i = 0 ; i < t ; i++ ) {
int index = k[ A.table[ i ].col ]++;
B.table[ index ].col = A.table[ i ].row;
B.table[ index ].row = A.table[ i ].col;
B.table[ index ].value = A.table[ i ].value;
}
&4.2 字符串
&4.2.1 串的定义
定长顺序存储表示:
#define MAXLEN 255
typedef struct {
char ch[ MAXLEN ];
int length;
} SString;
堆分配存储表示:
typedef struct {
char *ch;
int length;
} HString;
&4.2.2 模式匹配
&4.2.2.1 简单模式匹配
int Index( SString S , SString T ) {
int i = 1 , j = 1;
while( i <= S.length && j <= T.length ) {
if( S.ch[ i ] == T.ch[ j ] ) {
++i;
++j;
} else {
i = i - j + 2;
j = 1;
}
}
if( j > T.length ) {
return i - T.length;
} else {
return 0;
}
}
&4.2.2.2 改进字符串匹配(KMP)
P( 0 , k - 1 ) = S( i - k , i - 1 );
next数组求解:
void get_next( String T , int next[] ) {
int j = 0 , k = 0;
next[ 0 ] = 0;
while( j < T.length ) {
if( k == -1 || T.ch[ j ] == T.ch[ k ] ) {
j++;
k++;
next[ j ] = k;
} else {
k = next[ k ];
}
}
}
KMP算法:
int Index_KMP( String S , String T , int* next ) {
int i = 1 , j = 1;
while( i <= S.length && j <= T.length ) {
if( j == 0 || S.ch[ i ] == T.ch[ j ] ) {
++i;
++j;
} else {
j = next[ j ];
}
}
if( j > T.length ) {
return i - T.length;
} else {
return 0;
}
}
&4.2.2.3 KMP进一步优化
next数组修正值算法:
void get_nextval( String T , int nextval ) {
int i = 1 , j = 0;
nextval[ 1 ] = 0;
while( i < T.length ) {
if( j == 0 || T.ch[ i ] == T.ch[ j ] ) {
++i;
++j;
if( T.ch[ i ] != T.ch[ j ] ) {
nextval[ i ] = j;
} else {
nextval[ i ] = nextval[ j ];
}
} else {
j = nextval[ j ];
}
}
}
&5 树与二叉树
&5.2 二叉树
链式存储结构:
typedef struct BiTNode {
ElemType data;
struct BiTNode *lchild , *rchild;
} BiTNode , *BiTree;
&5.3 二叉树遍历
&5.3.1 递归
&5.3.1.1 先序遍历
void PreOrder( BiTree T ) {
if( T != NULL ) {
visit( T );
PreOrder( T -> lchild );
PreOrder( T -> rchild );
}
}
&5.3.1.2 中序遍历
void InOrder( BiTree T ) {
if( T != NULL ) {
InOrder( T -> lchild );
visit( T );
InOrder( T -> rchild );
}
}
&5.3.1.3 后序遍历
void PostOrder( BiTree T ) {
if( T != NULL ) {
PostOrder( T -> lchild );
PostOrder( T -> rchild );
visit( T );
}
}
&5.3.2 非递归
&5.3.2.1 中序遍历
void InOrder2( BiTree T ) {
InitStack( S );
BiTree p = T;
while( p || !IsEmpty( S ) ) {
if( p ) {
Push( S , p );
p = p -> lchild;
} else {
Pop( S , p );
visit( p );
p = p -> rchild;
}
}
}
&5.3.2.2 先序遍历
void PreOrder2( BiTree T ) {
InitStack( S );
BiTree p = T;
while( p || !IsEmpty( S ) ) {
if( p ) {
visit( p );
Push( S , p );
p = p -> lchild;
} else {
Pop( S , p );
p = p -> rchild;
}
}
}
&5.3.2.3 后序遍历
void PostOrder2( BiTree T ) {
InitStack( S );
BiTree p = T;
BiTree r = NULL;
while( p || !IsEmpty( S ) ) {
if( p ) {
Push( S , p );
p = p -> lchild;
} else {
GetTop( S , p ); //只读不取
if( p - > rchild && p -> rchild != r ) { //右结点没被访问过
p = p -> rchild;
} else {
Pop( S , p );
visit( p );
r = p;
p = NULL;
}
}
}
}
&5.3.3 层次遍历
void LevelOrder( BiTree T ) {
InitQueue( Q );
BiTree p;
EnQueue( Q , T );
while( !IsEmpty( Q ) ) {
DeQueue( Q , p );
visit( p );
if( p -> lchild != NULL ) {
EnQueue( Q , p -> lchild );
}
if( P -> rchild != NULL ) {
EnQueue( Q , p -> rchild );
}
}
}
&5.4 线索二叉树
&5.4.1 存储结构
typedef struct ThreadNode {
ElemType data;
struct ThreadNode *lchild , *rchild;
int ltag , rtag;
} ThreadNode , *ThreadTree;
&5.4.2 线索化
中序遍历递归线索化:
void InThread( ThreadTree &p , ThreadTree &pre ) {
if( p != NULL ) {
InThread( p -> lchild , pre );
if( p -> lchild == NULL ) {
p -> lchild = pre;
p -> ltag = 1;
}
if( pre != NULL && pre -> rchild == NULL ) {
pre -> rchild = p;
pre -> rtag = 1;
}
pre = p;
InThread( p -> rchild , pre );
}
}
void CreateInThread( ThreadTree T ) {
ThreadTree pre = NULL;
if( T != NULL ) {
InThread( T , pre );
pre -> rchild = NULL;
pre -> rtag = 1;
}
}
&5.4.3 遍历
中序序列第一个结点:
ThreadNode *Firstnode( ThreadNode *p ) {
while( p -> ltag == 0 ) {
p = p -> lchild;
return p;
}
}
结点p在中序序列下的后续:
ThreadNode *Nextnode( ThreadNode *p ) {
if( p -> rtag == 0 ) {
return Firstnode( p -> rchild );
} else {
return p -> rchild;
}
}
中序序列最后一个结点:
ThreadNode *Lastnode( ThreadNode *p ) {
while( p -> rtag == 0 ) {
p = p -> rchild;
return p;
}
}
结点p在中序序列下的前驱:
ThreadNode *Prenode( ThreadNode *p ) {
if( p -> ltag == 0 ) {
return Firstnode( p -> lchild );
} else {
return p -> lchild;
}
}
&5.5 树、森林
&5.5.1 树的存储结构
&5.5.1.1 双亲表示法
#define MAX_TREE_SIZE 100
typedef struct {
ElemType data;
int parent;
} PTNode;
typedef struct {
PTNode nodes[ MAX_TREE_SIZE ];
int n;
} PTree;
&5.5.1.2 孩子兄弟表示法
typedef struct CSNode {
ElemType data;
struct CSNode *firstchild , *nextsibling;
} CSNode , *CSTree;
&5.6 树、二叉树应用
&5.6.1 二叉排序树
二叉排序树非递归查找:
BSTNode *BST_Search( BiTree T , ElemType key ) {
while( T != NULL && key != T -> data ) {
if( key < T -> data) {
T = T -> lchild;
} else {
T = T -> rchild;
}
}
return T;
}
插入:
int BST_Insert( BiTree &T , KeyType k ) {
if( T == NULL ) {
T = ( BiTree ) malloc ( sizeof( BSTNode ) );
T -> key = k;
T -> lchild = T -> rchild = NULL;
return 1;
} else if( k == T -> key ) {
return 0;
} else if( k < T -> key ) {
return BST_Insert( T -> lchild , k );
} else {
return BST_Insert( T -> rchild , k );
}
}
构造:
void Creat_BST( BiTree &T , KeyType str[] , int n ) {
T = NULL;
int i = 0;
while( i < n ) {
BST_Insert( T , str[ i ] );
i++;
}
}
&5.6.2 平衡二叉树
插入:
1)LL平衡(左孩子的左子树不平衡):左孩子替代根节点,根节点变为右子树根节点
2)RR平衡(右孩子的右子树不平衡):右孩子替代根节点,根节点变为左子树根节点
3)LR平衡(左孩子的右子树不平衡):左孩子的右子树根节点替代左孩子,再替代根节点,根节点变为右子树根节点
4)RL平衡(右孩子的左子树不平衡):右孩子的左子树根节点替代右孩子,再替代根节点,根节点变为左子树根节点
&6 图
&6.1 图的存储及操作
&6.1.1 邻接矩阵
存储结构:
#define MaxVertxNum 100
typedef char VertexType;
typedef int EdgeType;
typedef struct {
VertexType Vex[ MaxVertexNum ]; //顶点表
EdgeType Edge[ MaxVertexNum ][ MaxVertNum ];
int vexnum , arcnum;
}
&6.1.2 邻接表法
存储结构:
#define MaxVertxNum 100
typedef struct ArcNode { //边表结点
int adjvex;
struct ArccNode *next;
} ArcNode;
typedef struct VNode { //顶点表结点
VertexType data;
ArcNode *first;
} VNode , AdjList[ MaxVertxNum ];
typedef struct {
AdjList vertices;
int vexnum , arcnum;
} ALGraph;
&6.2 图的遍历
&6.2.1 广度优先搜索
&6.2.1.1 搜索算法伪代码
bool visited[ MAX_VERTEX_NUM ];
void BFSTraverse( Graph G ) {
for( i = 0 ; i < G.vexnum ; ++i ) {
visited[ i ] = FALSE;
}
InitQueue( Q );
for( i = 0 ; i < G.vexnum ; ++i ) {
if( !visited[ i ] ) {
BFS( G , i );
}
}
}
void BFS( Graph G , int v ) {
visit( v );
visited[ v ] = true;
EnQueue( Q , v );
while( !IsEmpty( Q ) ) {
DeQueue( Q , v );
for( w = FirstNeighbor( G , v ) ; w >= 0 ; w = NextNeighbor( G ,v ,w ) ) {
if( !visited[ w ] ) {
visit( w );
visited[ w ] = true;
EnQueue( Q , w );
}
}
}
}
&6.2.1.2 BFS求解单源最短路径
void BFS_MIN_Distance( Graph G , int u ) {
for( i = 0 ; i < G.vexnum ; ++i ) {
d[ i ] = ∞;
}
visited[ u ] = true;
d[ u ] = 0;
EnQueue( Q , u );
while( !IsEmpty( Q ) ) {
DeQueue( Q , u );
for( w = FirstNeighbor( G , u ) ; w >= 0 ; w = NextNeighbor( G , u ,w ) ) {
if( !visited[ w ] ) {
visited[ w ] = true;
d[ w ] = d[ u ] + 1;
EnQueue( Q , w );
}
}
}
}
&6.2.2 深度优先搜索
&6.2.2.1 搜索算法伪代码
递归:
bool visited[ MAX_VERTEX_NUM ];
void DFSTraverse( Graph G ) {
for( v = 0 ; v < G.vexnum ; ++v ) {
visited[ v ] = false;
}
for( v = 0 ; v < G.vexnum ; ++v ) {
if( !visited[ v ] ) {
DFS( G , v );
}
}
}
void DFS( Graph G , int v ) {
visit( v );
visited[ v ] = true;
for( w = FirstNeighbor( G , v ) ; w >= 0 ; w = NextNeighbor( G , v ,w ) ) {
if( !visited[ w ] ) {
DFS( G , w );
}
}
}
非递归:
void DFS_Non_RC( AGraph &G , int v ) {
int w;
InitStack( S );
for( i = 0 ; i < G.vexnum ; i++ ) {
visited[ i ] = false;
}
Push( S , v );
visited[ v ] = true;
while( !IsEmpty( S ) ) {
k = Pop( S );
visit( k );
for( w = FirstNeighbor( G , k ) ; w >= 0 ; w = NextNeighbor( G , k , w ) ) {
if( !visited[ w ] ) {
Push( S , w );
visited[ w ] = true;
}
}
}
}
&6.2.2.2 输出所有简单路径
void FindPath( AGraph &G , int u , int v , int path[] , int d ) {
int w , i;
ArcNode *p;
d++;
path[ d ] = u;
visited[ u ] = 1;
if( u == v ) {
print( path[] );
}
p = G -> agjlist[ u ].firstarc;
while( p != NULL ) {
w = p -> adjvex;
if( visited[ w ] == 0 ) {
FindPath( G , w , v , path , d );
}
p = p -> nextarc;
}
visited[ u ] = 0;
}
&6.3 图的应用
&6.3.1 最小生成树
&6.3.1.1 通用最小生成算法
伪代码:
GENERIC_MST( G ) {
T = null;
while T 未形成一棵生成树;
do 找到一条最小代价边(u,v)并且加入T后不会产生回路;
T = T∪(u,v);
}
&6.3.1.2 Prim算法(普里姆)
简单实现:
void Prim( G , T ) {
T = 空集;
U = { w };
while( ( V - U ) != 空集) {
设(u,v)是使u属于U与v属于(V-U),且权值最小的边;
T = T ∪ {(u,v)}; //边归入树
U = U ∪ { v }; //顶点归入树
}
}
&6.3.1.3 Kruskal算法(克鲁斯卡尔)
简单实现:
void Kruskal( V , T ) {
T = V;
numS = n;
while( numS > 1 ) {
从E中取出权值最小的边(u,v);
if(v和u属于T的不同的连通分量){
T = T ∪ {(u,v)}; //边归入树
numS--;
}
}
}
&6.3.2 拓扑排序
排序算法:
bool TopologicalSort( Graph G ) {
InitStack( S );
for( int i = 0 ; i < G.vexnum ; i++ ) {
if( indegree[ i ] == 0 ) { //计入所有度为0的顶点进栈
Push( S , i );
}
}
int count = 0;
while( !IsEmpty( S ) ) {
Pop( S , i );
print[ count++ ] = i;
for( p = G.vertices[ i ].firstarc ; p ; p = p -> nextarc ) {
v = p -> adjvex;
if( !( --indegree[ v ] ) ) { //i指向的顶点入度减1,为0的顶点压入栈S
Push( S , v );
}
}
}
if( count < G.vexnum ) {
return false;
} else {
return true;
}
}
&6.4 归纳总结
&6.4.1 取邻接顶点的下一个邻接顶点
邻接矩阵:
int NextNeighbor( MGraph &G , int x , int y ) {
if( x != -1 && y != -1 ) {
for( int col = y + 1 ; col < G.vexnum ; col++ ) {
if( G.Edge[ x ][ col ] > 0 && G.Edge[ x ][ col ] < maxWeight ) {
return col;
}
}
return -1;
}
}
邻接表:
int NextNeighbor( ALGraph &G , int x , int y ) {
if( x != -1 ) {
ArcNode *p = G.vertices[ x ].first;
while( p != NULL && p -> data != y ) {
p = p -> next;
}
if( p != NULL && p -> next != NULL ) {
return p -> next -> data;
}
}
return -1;
}
&7 查找
&7.1 顺序查找和折半查找
&7.1.1 一般线性表的顺序查找
typedef struct {
ElemType *elem;
int TableLen;
} SSTable;
int Search_Seq( SSTable ST , ElemType key ) {
ST.elem[ 0 ] = key;
for( i = ST.TableLen ; ST.elem[ i ] != key ; --i ) {
return i;
}
}
&7.1.2 折半查找
非递归:
int Binary_Search( SeqList L , ElemType key ) {
int low = 0 , high = L.TableLen - 1 , mid;
while( low <= high ) {
mid = ( low + high ) / 2;
if( L.elem[ mid ] == key ) {
return mid;
} else if( L.elem[ mid ] > key ) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
递归:
typedef struct {
ElemType *elem;
int length;
} SSTable;
int BinSearchRec( SSTable ST , ElemType key , int low , int high ) {
if( low > high ) {
return 0;
}
mid = ( low + high ) / 2;
if( key > ST.elem[ mid ] ) {
Search( ST , key , mid + 1 , high );
} else if( key < ST.elem[ mid ] ) {
Search( ST , key , low , mid - 1 );
} else {
return mid;
}
}
&8 排序
&8.1 插入排序
&8.1.1 直接插入排序
void InsertSort( ElemType A[] , int n ) {
int i , j;
for( i = 2 ; i <= n ; i++ ) {
if( A[ i ] < A[ i - 1 ] ) {
A[ 0 ] = A[ i ];
for( j = i - 1 ; A[ 0 ] < A[ j ] ; --j ) {
A[ j + 1 ] = A[ j ]; //检测的位置在插入位置的前一个位置
}
A[ j + 1 ] = A[ 0 ];
}
}
}
&8.1.2 折半插入排序
void InsertSort( ElemType A[] , int n ) {
int i , j , low , high , mid;
for( i = 2 ; i < n ; i++ ) {
A[ 0 ] = A[ i ];
low = 1;
high = i - 1;
while( low <= high ) {
mid = ( low + high ) / 2;
if( A[ mid ] > A[ 0 ] ) {
high = mid - 1;
} else {
low = mid + 1;
}
}
for( j = i - 1 ; j >= high + 1 ; --j ) {
A[ j + 1 ] = A[ j ];
}
A[ high + 1 ] = A[ 0 ];
}
}
&8.1.3 希尔排序
void ShellSort( ElemType A[] , int n ) {
for( dk = n / 2 ; dk >= 1 ; dk = dk / 2 ) { //步长变化
for( i = dk + 1 ; i <= n ; ++i ) { //从第一个步长开始遍历
if( A[ i ] < A[ i - dk ] ) {
A[ 0 ] = A[ i ];
for( j = i - dk ; j > 0 && A[ 0 ] < A[ j ] ; j -= dk ) { //交换后移
A[ j + dk ] = A[ j ];
}
A[ j + dk ] = A[ 0 ]; //插入
}
}
}
}
&8.2 交换排序
&8.2.1 冒泡排序
void BUbbleSort( ElemType A[] , int n ) {
for( i = 0 ; i < n - 1 ; i ++ ) {
flag = false;
for( j = n - 1 ; j > i ; j-- ) {
if( A[ j - 1 ] > A[ j ] ) {
swap( A[ j - 1 ] , A[ j ] );
flag = true;
}
}
if( flag == false ) {
return;
}
}
}
&8.2.2 快速排序
void QuickSort( ElemType A[] , int low ,int high ) {
if( low < high ) {
int pivotpos = Partition( A , low , high );
QuickSort( A , low , pivotpos - 1 );
QuickSort( A , pivotpos + 1 , high );
}
}
int Partition( ElemType A[] , int low ,int high ) {
ElemType 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; //小于low均小于pivot,大于low均大于pivot
return low;
}
&8.3 选择排序
&8.3.1 简单选择排序
void SelectSort( ElemType A[] , int n ) {
for( i = 0 ; i < n - 1 ; i++ ) {
min = i;
for( j = i + 1 ; j < n : j++ ) {
if( A[ j ] < A[ min ] ) {
min = j;
}
}
if( min != i ) {
swap( A[ i ] , A[ min ] );
}
}
}
&8.3.2 堆排序
建立大根堆:
void BuildMaxHeap( ElemType A[] , int len ) {
for( int i = len / 2 ; i > 0 ; i-- ) {
HeadAdjust( A , i , len );
}
}
void HeadAdjust( ElemType A[] , int k , int len ) {
A[ 0 ] = A[ k ];
for( i = 2 * k ; i <= len ; i *= 2 ) {
if( i < len && A[ i ] < A[ i + 1 ] ) {
i++;
}
if( A[ 0 ] >= A[ i ] ) {
break;
} else {
A[ k ] = A[ i ];
k = i;
}
}
A[ k ] = A[ 0 ];
}
排序算法:
void HeadSort( ElemType A[] , int len ) {
BuildMaxHeap( A , len );
for( i = len ; i > 1 ; i-- ) {
Swap( A[ i ] , A[ 1 ] );
HeadAdjust( A , 1 , i - 1 );
}
}
&8.4 归并排序和基数排序
&8.4.1 归并排序
两个有序表排序成一个有序表:
ElemType *B = ( ElemType *) malloc ( ( n + 1 ) * sizeof( ElemType ) );
void Merge( ElemType A[] , int low , int mid , int high ) {
for( int k = low ; k <= high ; k++ ) {
B[ k ] = A[ k ];
}
for( i = low , j = mid + 1 , k = i ; 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( ElemType A[] , int low , int high ) {
if( low < high ) {
int mid = ( low + high ) / 2;
MergeSort( A , low , mid );
MergeSort( A , mid + 1 , high );
Merge( A , low , mid , high );
}
}