数据结构书上关键算法
顺序表的存储结构
# define MAXSIZE 100
typedef struct {
ElemType * elem;
int length;
} SqList;
顺序表的操作
顺序表的初始化
Status InitList ( SqList & L) {
L. elem = new ElemType[ MAXSIZE] ;
if ( ! L. elem) exit ( OVERFLOW) ;
L. length = 0 ;
return OK;
}
顺序表的取值
Status GetElem ( SqList L, int i, ElemType & e) {
if ( i< 1 || i> L. length) return ERROR;
e = L. elem[ i- 1 ] ;
return OK;
}
顺序表的查找
int LocateElem ( SqList L, ElemType) {
for ( int i = 0 ; i < L. length; i++ )
if ( L. elem[ i] == e) return i+ 1 ;
return 0 ;
}
顺序表的插入
Status ListInsert ( SqList & L, int i, ElemType) {
if ( ( i< 1 ) || ( i> L. length+ 1 ) ) return ERROR;
if ( L. length== MAXSIZE) return ERROR;
for ( int j= L. length- 1 ; j>= i- 1 ; j-- )
L. elem[ j+ 1 ] = L. elem[ j] ;
L. elem[ i- 1 ] = e;
++ L. length;
return OK;
}
顺序表的删除
Status ListDelete ( SqList & L, & L, int i) {
if ( ( i< 1 ) || ( i> L. length) ) return ERROR;
for ( int j= i; j<= L. length- 1 ; j++ )
L. elem[ j- 1 ] = L. elem[ j] ;
-- L. length;
return OK;
}
结构体指针描述“单链表的存储结构”
typedef struct LNode {
ElemType data;
struct LNode * next;
} LNode, * LinkList;
单链表的操作
单链表的初始化
Status InitList ( LinkList & L) {
L = new LNode;
L-> next = NULL ;
return OK;
}
单链表的取值
Status GetElem ( LinkList L, int i, ElemType & e) {
p= L-> next; j= 1 ;
while ( p&& j< 1 )
{
p = p-> next;
++ j;
}
if ( ! p|| j> 1 ) return ERROR;
e = p-> data;
return OK;
}
单链表的按值查找
LNode * LocateElem ( LinkList L, ElemType e) {
p = L-> next;
while ( p && p-> data!= e)
p = p-> next;
return p;
}
单链表的插入
Status ListInsert ( LinkList & L, int i, ElemType e) {
p= L; j= 0 ;
while ( p&& ( j< i- 1 ) )
{
p = p-> next; ++ j;
}
if ( ! p|| j> i- 1 ) return ERROR;
s = new LNode;
s-> data = e;
s-> next = p-> next;
p-> next = s;
return OK;
}
单链表的删除
Status ListDelete ( LinkList & L, int i) {
p = L; j = 0 ;
while ( ( p-> next) && ( j< i- 1 ) )
{
p = p-> next; ++ j;
}
if ( ! ( p-> next) || ( j> i- 1 ) ) return ERROR;
q = p-> next;
p-> next = q-> next;
delete q;
return OK;
}
前插法创建单链表
void CreateList_H(LinkList &L,int n){
//逆位序输入n个元素的值,建立带表头结点的单链表L
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
for(int i=0;i<n;++i){
p = new LNode; //生成新结点*p
cin >> p->data; //输入元素值赋给新结点*p的数据域
p->next = L->next;L->next = p; //将新结点*p插入到头结点之后
}
}
后插法创建单链表
void CreateList_R(LinkList &L,int n){
//逆位序输入n个元素的值,建立带表头结点的单链表L
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
r = L; //尾指针r指向头结点
for(int i=0;i<n;++i){
p = new LNode; //生成新结点*p
cin >> p->data; //输入元素值赋给新结点*p的数据域
p->next = NULL; r->next = p; //将新结点*p插入到㞑结点*r之后
r = p; //r指向新的尾结点*p
}
}
双向链表的存储结构
typedef struct DuLNode{
ElemType data; //数据域
struct DuLNode *prior; //指向直接前驱
struct DuLNode *next; //指向直接后继
}DuLNode,*DuLinkList;
双向链表的插入
Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
//在带头结点的双向链表L中第i个位置之前插入元素e
if(!(p= GetElem_DuL(L,i))) //在L中确定第i个元素的位置指针p
return ERROR; //p为NULL时,第i个元素不存在
s = new DuLNode; //生成新结点*s
s->data = e; //将结点*s数据域置为e
s->prior = p->prior; //将结点*s插入L中
p->prior->next = s;
s->next = p;
p->prior = s;
return OK;
}
双向链表的删除
Status ListDelete_DuL(DuLinkList &L,int i){
//删除带头结点的双向链表L中的第i个元素
if(!(p= GetElem_DuL(L,i))) //在L中确定第i个元素的位置指针p
return ERROR; //p为NULL时,第i个元素不存在
p->prior->next = p->next;//修改被删结点的前驱结点的后继指针
delete p; //释放被删结点的空间
return OK;
}
顺序栈的存储结构
# define MAXSIZE 100
typedef struct {
SElemType * base;
SElemType * top;
int stacksize;
} SqStack;
栈的操作
顺序栈的初始化
Status InitStack(SqStack &S){
//构造一个空栈
S.base = new SElemType[MAXSIZE]; //为顺序栈动态分配一个最大容量为MAXSIZE的数组空间
if(!S.base) exit(OVERFLOW); //存储分配失败
S.top = S.base; //top初始为base,空栈
S.stacksize = MAXSIZE; //stacksize置为栈的最大容量MAXSIZE
return OK;
}
顺序栈的入栈
Status Push(SqStack &S,SElemType e){
//插入元素e为新的栈顶元素
if(S.top-S.base == S.stacksize) return ERROR; //栈满
*S.top++=e; //元素e压入栈顶,栈顶指针加1
return OK;
}
顺序栈的出栈
Status Pop(SqStack &S,SElemType &e){
//删除S的栈顶元素,用e返回其值
if(S.top == S.base) return ERROR; //栈空
e = *--S.top; //栈顶指针减1,将栈顶元素赋给e
return OK;
}
取栈顶元素
SElemType GetTop(SqStack S){
//返回S的栈顶元素,不修改栈顶指针
if(S.top != S.base) //栈非空
return *(S.top-1); //返回栈顶元素的值,栈顶指针不变
}
链栈的存储结构
typedef struct StackNode{
ElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
链栈的初始化
Status InitStack(linkStack &S){
//构造一个空栈S,栈顶指针置空
S = NULL;
return OK;
}
链栈的入栈
Status Push(LinkStack &S,SElemType e){
//在栈顶插入元素e
p = new StackNode; //生成新结点
p->data = e; //将新结点数据域置为e
p->next = S; //将新结点插入栈顶
S = p; //修改栈顶指针为p
return OK;
}
链栈的出栈
Status Pop(LinkStack &S,SElemType &e){
//删除S的栈顶元素,用e返回其值
if(S == NULL) return ERROR; //栈空
e = S->data; //将栈顶元素赋给e
p = S; //用p临时保存栈顶元素空间。以备释放
S = S->next; //修改栈顶指针
delete p; //释放原栈顶元素空间
return OK;
}
取链栈的栈顶元素
SElemType GetTop(LinkStack S){
//返回S的栈顶元素,不修改栈顶指针
if(S != NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
}
循环队列
队列的顺序存储结构
#define MAXQSIZE 100 //队列可能达到的最大长度
typedef struct {
QElemType *base; //存储空间的基地址
int front; //头指针
int rear; //尾指针
}SqQueue;
循环队列的初始化
Status InitQueue(SqQueue &Q){
Q.base = new QElemType[MAXQSIZE]; //为队列分配一个最大容量为MAXQSIZE的数组空间
if(!Q.base) exit(OVERFLOW); //存储分配失败
Q.front = Q.rear = 0; //头指针和尾指针置为零,队列为空
return OK;
}
求循环队列的长度
int QueueLength(SqQueue Q){
//返回Q的元素个数,即队列的长度
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE; //括号中加的MAXQSIZE是为了防止出现负数
}
循环队列的入队
Status EnQueue(SqQueue &Q,QElemType e){
//插入元素e为Q的新的队尾元素
if((Q.rear+1)%MAXQSIZE == Q.front) //尾指针在循环意义上加1后等于头指针,表明队满
return ERROR;
Q.base[Q.rear] = e; //新元素插入队尾
Q.rear = (Q.rear+1)%MAXQSIZE; //队尾指针加1
return OK;
}
循环队列的出队
Status DeQueue(SqQueue &Q,QElemType &e){
//删除Q的队头元素,用e返回其值
if(Q.front == Q.rear) return ERROR; //队空
e = Q.base[Q.front]; //保存队头元素
Q.front = (Q.front+1)%MAXQSIZE; //队头指针加1
return OK;
}
取循环队列的队头元素
QElemType GetHead(SqQueue Q){
//返回Q的队头元素,不修改队友指针
if(Q.front != Q.rear) //队列非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变
}
链队
队列的链式存储结构
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct {
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
链队的初始化
Status InitQueue(LinkQueue &Q){
//构造一个空队列Q
Q.front = Q.rear = new QNode; //生成新结点作为头结点,队头和队尾指针指向此结点
Q.front->next = NULL; //头结点的指针域置空
return OK;
}
链队的入队
Status EnQueue(LinkQueue &Q,QElemType e){
p = new QNode; //为入队元素分配结点空间,用指针p指向
p->data = e; //将新结点的数据域置为e
p->next = NULL; Q.rear->next = p; //将新结点插入到队尾
Q.rear = p; //修改队尾指针
return OK;
}
链队的出队
Status DeQueue(LinkQueue &Q,QElemType &e){
//删除Q的队头元素,用e返回其值
if(Q.front == Q.rear) return ERROR; //若队列空,则返回ERROR
p = Q.front->next; //p指向队头元素
e = p->data; //e保存队头元素的值
Q.front->next = p->next; //修改头结点的指针域
if(Q.rear == p) Q.rear = Q.front; //最后一个元素被删,队尾指针指向头结点
delete p; //释放原队头元素的空间
return OK
}
取链队的队头元素
QElemType GetHead(LinkQueue Q){
//返回Q的队头元素,不修改队头指针
if(Q.front != Q.rear) //队列非空
return Q.front->next->data; //返回队头元素的值,队头指针不变
}
串的定长顺序存储结构
#define MAXLEN 255 //串的最大长度
typedef struct {
char ch[MAXLEN+1]; //存储串的一维数组
int length; //串的当前长度
}SString;
串的堆式顺序存储结构
typedef struct {
char *ch; //若是非空串,则按串长分配存储区,否则ch为NULL
int length; //串的当前长度
}HString;
串的链式存储结构
#define CHUNKSIZE 80 //可由用户定义的块大小
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *head,*tail; //串的头和尾指针
int length; //串的当前长度
}LString;
串的模式匹配算法–(没讲)
BF算法
int Index_BF(SString S,SString T,int pos){
//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0
//其中,T非空,1 ≤ pos ≤ S.length
int i = pos,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; //匹配失败
}
//BF算法完整代码
#include <iostream>
using namespace std;
int Index_BF(string A, string B, int pos) {
int i = pos, j = 0;
while (i < A.length() && j < B.length()) {
//两个字符串均为比较到串尾(只有有一个到串尾就跳出循环)
if (A[i] == B[j]) {
i++;
j++;
}
else {
//匹配失败指针回溯
i = i - j + 1;
j = 0;
}
}
if (j >= B.length()) return i - B.length();
else return -1;
}
int main() {
string a = "abckjsef";
string b = "kjs";
int flag = Index_BF(a, b, 4);
if (flag == -1) cout << "子串在主串之中不存在!" << endl;
else cout << "子串在主串中起始位置为:" << flag + 1 << endl;
return 0;
}
KMP算法
int Index_KMP(SString S,SString T,int pos){
//利用模式串T的next函数求T在主串S中第pos个字符之后的位置
//其中,T非空,1 ≤ pos ≤ S.length
int i = pos,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; //匹配失败
}
//完整KMP算法代码
#include <iostream>
#include <cstring>
#include <string>
#include <set>
#include <map>
using namespace std;
void BuildPatchMatchTable(int *partMatchTable, char *findstr)
{
if(findstr == NULL)
return;
partMatchTable[0] = 0;
int sizefind = strlen(findstr);
for(int i = 1; i < sizefind; ++i)
{
set<string> preset;
string tmppre = "";
tmppre = findstr[0];
preset.insert(tmppre);
for(int j = 1; j < i; ++j)
{
tmppre = tmppre + findstr[j];
preset.insert(tmppre);
}
set<string> postset;
string tmppost = "";
tmppost = findstr[i];
postset.insert(tmppost);
for(int j = i - 1; j > 0; --j)
{
tmppost = findstr[j] + tmppost;
postset.insert(tmppost);
}
set<string> comset;
for(set<string>::iterator beg = preset.begin(); beg != preset.end(); ++beg)
{
if(postset.count(*beg) > 0)
comset.insert(*beg);
}
int maxlen = 0;
for(set<string>::iterator beg = comset.begin(); beg != comset.end(); ++beg)
{
if((*beg).size() > maxlen)
maxlen = (*beg).size();
}
partMatchTable[i] = maxlen;
}
}
int kmp(char *srcstr, char *findstr)
{
if(srcstr == NULL || findstr == NULL)
return -1;
int lensrc = strlen(srcstr);
int lenfind = strlen(findstr);
int *partMatchTable = new int[lenfind];
BuildPatchMatchTable(partMatchTable, findstr);
for(int i = 0; i < lenfind; ++i)
cout << findstr[i] << "\t" << partMatchTable[i] << endl;
int curFind = 0;
for(int i = 0; i < lensrc; )
{
if(findstr[curFind] == srcstr[i])
{
++i;
++curFind;
}
else
{
if(curFind == 0)
++i;
else
{
int movestep = curFind - partMatchTable[curFind-1];
i += movestep;
curFind = 0;
}
}
if(curFind == lenfind)
{
delete []partMatchTable;
return i - lenfind;
}
}
return -1;
delete []partMatchTable;
}
int main()
{
char srcStr[] = "bbc abcdab abcdabcdabde";
char findStr[] = "abcdabd";
cout << "pos:" << kmp(srcStr, findStr) << endl;
char srcStr2[] = "bbc abcdab abcdabcdabdezzz";
char findStr2[] = "zzz";
cout << "pos:" << kmp(srcStr2, findStr2) << endl;
char srcStr3[] = "bbc abcdab abcdabcdabde";
char findStr3[] = "zzz";
cout << "pos:" << kmp(srcStr3, findStr3) << endl;
}
二叉树的存储结构
# define MAXSIZE 100
typedef TElemType SqBiTree[ MAXSIZE] ;
SqBiTree bt;
typedef struct BiTNode {
TElemType data;
struct BiTNode * lchild, * rchild;
} BiTNode, * BiTree;
遍历二叉树
void InOrderTraverse ( Bitree T) {
if ( T) {
InOrderTraverse ( T-> lchild) ;
cout << T-> data;
InOrderTraverse ( T-> rchild) ;
}
}
void InOrderTraverse ( Bitree T) {
InitStack ( S) ; p = T;
q = new BiTNode;
while ( p || ! StackEmpty ( S) ) {
if ( p)
{
Push ( S, p) ;
p = p-> lchild;
}
else
{
Pop ( S, q) ;
cout << q-> data;
p = q-> rchild;
}
}
}
先序遍历的顺序建立二叉链表
void CreateBiTree ( BiTree & T) {
char ch;
cin >> ch;
if ( ch == '#' ) T = NULL ;
else
{
T = new BiTNode;
T-> data = ch;
CreateBiTree ( T-> lchild) ;
CreateBiTree ( T-> rchild) ;
}
}
复制二叉树
void Copy(BiTree T,BiTree &NewT){
//复制一棵和T完全相同的二叉树
if(T == NULL) //如果是空树,递归结束
{
NewT = NULL;
return;
}
else{
NewT = new BiTNode;
NewT->data = T->data; //复制根节点
Copy(T->lchild,NewT->lchild); //递归复制左子树
Copy(T->rchild,NewT->rchild); //递归复制右子树
}
}
计算二叉树的深度
int Depth(BiTree T){
//计算二叉树T的深度
if(T == NULL) return 0; //如果是空树,深度为0,递归结束
else{
int m,n;
m = Depth(T->lchild); //递归计算左子树的深度记为m
n = Depth(T->rchild); //递归计算右子树的深度记为n
if(m > n) return (m+1); //二叉树的深度为m与n的较大者加1
else return (n+1);
}
}
统计二叉树T中结点的个数(PTA中有函数题)
int NodeCount(BiTree T){
//统计二叉树T中结点的个数
if(T == NULL) return 0; //如果是空树,则结点个数为0,递归结束
else //否则结点个数为左子树的结点个数+右子树结点个数+1
return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
}
#include <iostream>
using namespace std;
typedef char BTDataType;
typedef struct BiTNode
{
BTDataType data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
//按先序次序输入二叉树结点的值(一个字符),创建二叉链表表示的二叉树T
void CreateBiTree(BiTree& T) {
char ch;
cin >> ch;
if (ch == '#') T = NULL; //递归结束,建空树
else
{
T = new BiTNode; //生成根结点
T->data = ch; //根节点数据域置为ch
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
}
}
//为了方便测试,不用一个个输入创建二叉树,这个数组是先序存放的二叉树,深度为4
char treeArray[] = { 'A','B','#','C','D','#','#','E','#','#','F','#','G','H','#','#','#' };
int i = 0;
void CreateBiTreeTest(BiTree& T) {
char ch;
ch = treeArray[i++];
if (ch == '#') T = NULL;
else
{
T = new BiTNode;
T->data = ch;
CreateBiTreeTest(T->lchild);
CreateBiTreeTest(T->rchild);
}
}
//复制一颗和T完全相同的二叉树
void Copy(BiTree T, BiTree& NewT)
{
if (T == NULL)
{
NewT = NULL;
return;
}
else
{
NewT = new BiTNode;
NewT->data = T->data; //复制根节点
Copy(T->lchild, NewT->lchild); //递归复制左子树
Copy(T->rchild, NewT->rchild); //递归复制右子树
}
}
//计算二叉树的深度--在后序遍历二叉树的基础上进行的运算
int Depth(BiTree T)
{
int m = 0, n = 0;
if (T == NULL) return 0;
else
{
m = Depth(T->lchild); //递归计算右子树的深度m
n = Depth(T->rchild); //递归计算左子树的深度n
if (m > n) return m + 1; //左右深度较大者+1根节点
else return n + 1;
}
}
//统计二叉树T中结点的个数
int NodeCount(BiTree T)
{
if (T == NULL) return 0;
else return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
}
//计算二叉树叶子结点总数
int LeadCount(BiTree T)
{
if (T == NULL) return 0;
if (T->lchild == NULL && T->rchild == NULL) return 1;
else return LeadCount(T->lchild) + LeadCount(T->rchild);
}
int main()
{
BiTree T;
CreateBiTreeTest(T); i = 0; //方便测试,不用输入创建
cout << Depth(T) << endl;
cout << NodeCount(T) << endl;
cout << LeadCount(T) << endl;
return 0;
}
线索二叉树
二叉树的二叉线索存储表示
typedef struct BiThrNode {
TElemType data;
struct BiThrNode * lchild, * rchild;
int LTag, RTag;
} BiThrNode, * BiThrTree;
遍历中序线索二叉树
void InOrderTraverse_Thr(BiThrTree T){
//T指向头结点,头结点的左链lchild指向根节点,
//中序遍历二叉线索树T的非递归算法,对每个数据元素直接输出
p = T->lchild; //p指向根节点
while(p != T) //空树或遍历结束时,p==T
{
while(p->lTag == 0) p = p->lchild; //沿左孩子向下
cout << p->data; //访问其左子树为空的结点
while(p->RTag == 1 && p->rchild != T){
p = p->rchild;cout << p->data; //沿右线索访问后继结点
}
p = p->rchild; //转向p的右子树
}
}
哈夫曼树
哈夫曼树的存储表示
typedef struct{
int weight; //结点的权值
int parent,lchild,rchild; //结点的双亲、左孩子、右孩子的下标
}HTNode,*HuffmanTree;
构造哈夫曼树
void CreateHuffmanTree(HuffmanTree &HT,int n){
//构造哈夫曼树
if(n <= 1) return;
int m = 2 * n - 1;
HT = new HTNode [m+1]; //0号单元未用,所以需要动态分配m+1个单元,HT[m]表示根节点
for(int i = 1;i <= m;++i) //将1~m号单元的双亲、左孩子、右孩子的下标都初始化为0
{HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}
for(int i = 1;i <= n;++i) //输入前n个单元中叶子结点的权值
cin >> HT[i].weight;
/*初始化工作结束,下面开始创建哈夫曼树*/
for(int i = n+1;i <= m;++i){
//通过n-1次的选择、删除、合并来创建哈夫曼树
Select(HT,i-1,s1,s2);
//在HT[k](1≤k≤i-1)中选择两个其双亲域为0且权值最小的结点,并返回它们在HT中的序号s1和s2
HT[s1].parent = i;HT[s2].parent = i;
//得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由0改为i
HT[i].lchild = s1;HT[i].rchild = s2; // s1,s2分别作为i的左右孩子
HT[i].weight = HT[s1].weight + HT[s2].weight; //i的权值为左右孩子权值之和
}
}
邻接表
图的邻接表存储表示
#define MVNum 100 //最大顶点数
typedef struct ArcNode //边结点
{
int adjvex; //该边所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
OtherInfo info; //和边相关的信息
}ArcNode;
typedef struct Vnode //顶点信息
{
VerTexType data;
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum]; //AdjList表示邻接表类型
typedef struct{
AdjList vertices;
int vexnum,arcnum; //图的当前顶点数和边数
}ALGraph;
采用邻接表表示法创建无向图 (这个算法可能没讲,感觉特别生疏)
Status CreateUDG(ALGraph &G){
//采用邻接表表示法,创建无向图G
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
int i,k;
for(i = 0;i < G.vexnum;++i) //输入各点,构造表头结点表
{
cin >> G.vertices[i].data; //输入顶点值
G.vertices[i].firstarc = NULL; //初始化表头结点的指针域为NULL
}
for(k = 0;k < G.arcnum;++k) //输入各边、构造邻接表
{
cin >> v1 >> v2; //输入一条边依附的两个顶点
i = LocateElem(G,v1);j = LocateElem(G,v2);
//确定v1和v2在G中位置,即顶点在G.vertices中的序号
p1 = new ArcNode; //生成一个新的边结点*p1
p1->adjvex = j; //生成一个新的边结点*p1
p1->nextarc = G.vertices[i].firstarc;G.vertices[i].firstarc = p1;
//将新结点*p1插入v[i]的边表头部
p2 = new ArcNode; // 生成另一个对称的新的边结点*p2
p2->nextarc = G.vertices[j].firstarc;G.vertices[j].firstarc = p2;
//将新结点*p2插入顶点v[j]的边表首部
}
return OK;
}
顺序表
数据元素定义
typedef struct{
KeyType key; //关键字域
InfoType otherinfo; //其他域
}ElemType;
typedef struct{
ElemType *R; //存储空间基地址
int length; //当前长度
}SSTable;
顺序查找
int Search_Seq(SSTable ST,KeyType key){
//在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
for(int i = ST.length;i>=1;i--)
if(ST.R[i].key == key) return i; //从后往前找
return 0;
}
设置监视哨的顺序查找
int Search_Seq(SSTable ST,KeyType key){
//在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
ST.R[0].key = key; //“哨兵”
for(int i = ST.length;ST.R[i].key!=key;--i)//从后往前找
return i;
}
折半查找(PTA编程题用到了该思想)
int Search_Bin(SSTable ST,KeyType key){
//在有序表ST中折半查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
int low=1,high = ST.length,mid; //置查找区间初值
while(low<=high){
mid = (low+high)/2;
if(key == ST.R[mid].key) return mid; //找到待查元素
else if(key<ST.R[mid].key) high = mid - 1; //继续在前一字表进行查找
else low = mid + 1; //继续在后一字表进行查找
}
return 0; //表中不存在待查元素
}
二叉排序树的二叉链表存储表示
typedef struct{
KeyType key; //关键字项
InfoType otherinfo; //其他数据项
}ElemType; //每个结点的数据域的类型
typedef struct BSTNode{
ElemType data; //每个结点的数据域包括关键字项和其他数据项
struct BSTNode *lchild,*rchild; //左右孩子指针
}BSTNode,*BSTree;
二叉排序树的查找
BSTree SearchBST(BSTree T,KeyType key){
//在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
if((!T) || key == T->data.key) return T; //查找结束
else if(key < T->data,key) return SearchBST(T->lchild,key); //在左子树中查找
else return SearchBST(T->rchild,key); //在右子树中查找
}
二叉排序树的插入
void InsertBST(BSTree &T,ElemType){
//当二叉排序树T中不存在关键字等于e.key的数据元素时,则插入该元素
if(!T){ //找到茶蕊位置,递归结束
S = new BSTNode; //生成新结点*S
S->data = e; //新结点*S的数据域置为e
S->lchild = S->rchild = NULL; //新结点*S作为叶子结点
T = S; //把新结点*S链接到已找到的插入位置
}
else if(e.key < T->data.key)
InsertBST(T->lchild,e); //将*S插入到左子树
else if(e.key > T->data.key)
InsertBST(T->rchild,e); //将*S插入到右子树
}
哈希表(没讲)
开放地址法散列表的存储表示
#define m 20 //散列表的表长
typedef struct{
KeyType key; //关键字项
InfoType otherinfo; //其他数据项
}HashTable[m];
散列表的查找
#define NULLKEY 0 //单元为空的标记
int SearchHash(HashTable HT,KeyType key){
//在散列表HT中查找关键字为key的元素,若查找成功,返回散列表的单元序号,否则返回-1
int H0 = H(key); //根据散列函数H(key)计算散列地址
if(HT[H0].key == NULLKEY) return -1; //若单元H0为空,则所查元素不存在
else if(HT[H0].key == key) return H0; //若单元H0中元素的关键字为key,则查找成功
else{
for(int i = 1;i < m;++i){
int Hi = (H0+i) % m; //按照线性探测法计算下一个散列地址Hi
if(HT[Hi].key == NULLKEY) return -1; //若单元Hi为空,则查找元素不存在
else if(HT[Hi].key == key) return Hi; //若单元Hi中元素的关键字为key,则查找成功
}
return -1;
}
}
排序
待排序记录的数据类型定义
#define MAXSIZE 20 //顺序表的最大长度
typedef int KeyType; //定义关键字类型为整型
typedef struct{
KeyType key; //关键字项
InfoType otherinfo; //其他数据项
}RedType; //记录类型
typedef struct{
RedType r[MAXSIZE+1]; //r[0]闲置或用做哨兵单元
int length; //顺序表长度
}SQList; //顺序表类型
直接插入排序(PTA中有函数题)
void InsertSort(SqList &L){
//对顺序表L做直接插入排序
int i,r,j;
if(L.r[i].key < L.r[i-1].key) //“<”,需将r[i]插入有序子表
{
L.r[0] = L.r[i]; //待插入的记录暂存到监视哨中
L.r[i] = L.r[i-1]; //r[i-1]后移
for(j = i - 2;L.r[0].key < L.r[j].key;--j) //从后向前寻找插入位置
L.r[j+1] = L.r[j]; //记录逐个后移,直到找到插入位置
L.r[j+1] = L.r[0]; //将r[0]即原r[i],插入到正确位置
}
}
折半插入排序(PTA中有题,但可以用bug写法)
/*----bug写法1----*/
void BInsertSort(SqList &L){
int a[]{12,24,24,45,45,53,90},i=1;
while(i<7){
L.r[i].key=a[i-1];
i++;
}
}
/*----bug写法2----*/
/*--两种bug原理一样--*/
void BInsertSort(SqList &L){
int a[]{12,24,24,45,45,53,90},i;
for(i=1;i<a.length;i++)
L.r[i].key=a[i-1];
}
}
void BInsertSort(SqList &L){
//对顺序表L做折半插入排序
for(int i = 2;i <= L.length;++i){
L.r[0] = L.r[i]; //将待插入的记录暂存到监视哨中
int low = 1,high = i - 1; //置查找区间初值
while (low <= high) //在r[low..high]中折半查找插入的位置
{
m = (low + high) / 2; //折半
if(L.r[0].key < L.r[m].key) high = m - 1; //插入点在前一子表
else low = m + 1; //插入点在后一子表
}
for(int j = i - 1;j >= high + 1;--j) L.r[j+1] = L.r[j]; //记录后移
L.r[high+1] = L.r[0]; //将r[0]即原r[i],插入到正确位置
}
}
冒泡排序(PTA中有函数题)
void BubbleSort(SqList &L){
//对顺序表L做冒泡排序
int m = L.length - 1,flag = 1; //flag用来标记某一趟排序是否发生交换
while((m>0) && (flag == 1)){
flag = 0; //flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
for(int j = 1;j <= m;j++)
if(L.r[j].key > L.r[j+1].key){
flag = 1; //flag置为1,表示本趟排序发生了交换
int t = L.r[j]; L.r[j] = L.r[j+1];L.r[j+1] = t; //交换前后两个记录
}
--m;
}
}
快速排序
int Partition(SqList &L,int low,int high){
//对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴的位置
L.r[0] = L.r[low]; //用子表的第一个记录做枢轴记录
pivotkey = L.r[low].key; //枢轴记录关键字保存在pivokey中
while(low < high) //从表的两端交替地向中间扫描
{
while(low<high && L.r[high].key >= pivokey) --high;
L.r[low] = L.r[high]; //将比枢轴记录小的记录移到低端
while(low<high && L.r[low].key <= pivokey) ++low;
L.r[high] = L.r[low]; //将比枢轴记录大的记录移到高端
}
L.r[low] = L.r[0]; //枢轴记录到位
return low; //返回枢轴位置
}
void QSort(SqList &L,int low,int high){
//调用前置初值:low=1;high=L.length;
//对顺序表L中的子序列L.r[low..high]做快速排序
if(low < high){ //长度大于1
pivotloc = Partition(L,low,high); //将L.r[low..high]一分为二,pivotloc是枢轴位置
QSort(L,low,pivotloc-1); //对左子表递归排序
QSort(L,pivotloc+1,high); //对右子表递归排序
}
}
void QuickSort(SqList &L){
//对顺序表L做快速排序
QSort(L,1,L.length);
}
选择排序
简单选择排序(PTA中有函数题)
void SelectSort(SqList &L){
//对顺序表L做简单选择排序
for(int i = 1;i<L.length;++i){ //在l.r[i..L.length]中选择关键字最小的记录
int k = i;
for(int j = i+1;j<=L.length;++j)
if(L.r[j].key < L.r[k].key) k = j; //k指向此趟排序中关键字最小的记录
if(k!=i)
{int t = L.r[i];L.r[i] = L.r[k];L.r[k] = t;} //交换r[i]与r[k]
}
}