数据结构书上算法

数据结构书上关键算法

顺序表的存储结构
#define MAXSIZE 100  //顺序表可能达到的最大长度
typedef struct {
    ElemType *elem;  //存储空间的基地址
    int length;  //当前长度
}SqList;  //顺序表的结构类型为SQList

顺序表的操作

顺序表的初始化
Status InitList(SqList &L){
    //构造一个空的顺序表L
    L.elem = new ElemType[MAXSIZE];  //为顺序表分配一个大小为MAXSIZE的数组空间
    if(!L.elem) exit(OVERFLOW);  //存储分配失败退出
    L.length = 0;  //空表长度为0
    return OK;
}
顺序表的取值
Status GetElem(SqList L,int i,ElemType &e){
    if(i<1||i>L.length) return ERROR; //判断i值是否合理,若不合理,返回ERROR
    e = L.elem[i-1]; //elem[i-1]单元存储第i个数据元素
    return OK;
}
顺序表的查找
int LocateElem(SqList L,ElemType){
    //在顺序表L中查找值为e的数据元素,返回其序号
    for (int i = 0; i < L.length; i++)
        if(L.elem[i]==e) return i+1;  //查找成功,返回序号i+1
    return 0;  //查找失败,返回0
}
顺序表的插入
Status ListInsert(SqList &L,int i,ElemType){
    //在顺序表L中第i个位置插入新的元素e,i值的合法范围是1 ≤ i ≤ L.length+1
    if((i<1)||(i>L.length+1)) return ERROR;  //i值不合法
    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;  //将新元素e放入第i个位置
    ++L.length;  //表长加1
    return OK;
}
顺序表的删除
Status ListDelete(SqList &L,&L,int i){
    //在顺序表L中删除第i个元素,i值的合法范围是1 ≤ i ≤ L.length
    if((i<1)||(i>L.length)) return ERROR;  //i值不合法
    for(int j=i;j<=L.length-1;j++)
        L.elem[j-1] = L.elem[j];  //被删除元素之后的元素前移
    --L.length;  //表长减1
    return OK;
}
结构体指针描述“单链表的存储结构”
typedef struct LNode{
    ElemType data;  //结点的数据域
    struct LNode *next;  //结点的指针域
}LNode,*LinkList;  //LinkList为指向结构体LNode的指针类型

单链表的操作

单链表的初始化
Status InitList(LinkList &L){
    //构造一个空的单链表L
    L = new LNode;  //生成新结点作为头结点,用头指针L指向头结点
    L->next = NULL;  //头结点的指针域置空
    return OK;
}
单链表的取值
Status GetElem(LinkList L,int i,ElemType &e){
    //在带头结点的单链表L中根据序号i获取元素的值,用e返回L中第i个数据元素的值
    p=L->next;j=1;  //初始化,p指向首元结点,计数器j初值赋为1
    while(p&&j<1)  //顺链域向后扫描,直到p为空或p指向第i个元素
    {
        p = p->next;  //p指向下一个结点
        ++j;  //计数器j相应加1
    }
    if(!p||j>1) return ERROR;  //i值不合法i > n或i ≤ 0
    e = p->data;
    return OK;
}
单链表的按值查找
LNode *LocateElem(LinkList L,ElemType e){
    //在带头结点的单链表L中查找值为e的元素
    p = L->next;  //初始化,p指向首元结点
    while(p && p->data!=e)  //顺链域向后扫描,直到p为空或p所指结点的数据域等于e
        p = p->next;  //p指向洗衣歌结点
    return p;  //查找成功返回值为e的结点地址p,查找失败p为NULL
}
单链表的插入
Status ListInsert(LinkList &L,int i,ElemType e){
    //在带头结点的单链表L中第i个位置插入值为e的新结点
    p=L;j=0;
    while(p&&(j<i-1))  
    {
        p = p->next;++j;  //查找第i-1个结点,p指向该结点
    }
    if(!p||j>i-1) return ERROR;  //i > n+1 或者i < 1
    s = new LNode;  //生成新结点*s
    s->data = e;  //将结点*s的数据域置为e
    s->next = p->next;  //将结点*s的指针域指向结点a[i]
    p->next = s;  //将结点*p的指针域指向结点*s
    return OK;
}
单链表的删除
Status ListDelete(LinkList &L,int i){
    //在带头结点的单链表L中,删除第i个元素
    p = L;j = 0;
    while((p->next) && (j<i-1))  //查找第i-1个结点,p指向该结点
    {
        p = p->next;++j;
    }
    if(!(p->next)||(j>i-1)) return ERROR;  //当i>n或i<1时,删除位置不合理
    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];  //0号单元存储根节点
SqBiTree bt;

//二叉树的二叉链表存储表示
typedef struct BiTNode{
    TElemType data;  //结点数据域
    struct BiTNode *lchild,*rchild;  //左右孩子指针
}BiTNode,*BiTree;

遍历二叉树

//中序遍历的递归算法
void InOrderTraverse(Bitree T){
    //中序遍历二叉树T的递归算法
    if(T){
        InOrderTraverse(T->lchild);  //中序遍历左子树
        cout << T->data;   //访问根节点
        InOrderTraverse(T->rchild);  //中序遍历右子树
    }
}

//中序遍历的非递归算法
void InOrderTraverse(Bitree T){
    //中序遍历二叉树T的非递归算法
    InitStack(S);p = T;
    q = new BiTNode;
    while(p || !StackEmpty(S)){
        if(p)  //p非空
        {
            Push(S,p);  //根指针进栈
            p = p->lchild;  //根指针进栈,遍历左子树
        }
        else
        {
            Pop(S,q);  //退栈
            cout << q->data;  //访问根节点
            p = q->rchild;  //遍历右子树
        }
    }  //while
}
先序遍历的顺序建立二叉链表
void CreateBiTree(BiTree &T){
    //按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
    char ch;
    cin >> ch;
    if(ch == '#') T = NULL;  //递归结束建空树
    else  //递归创建二叉树
    {
        T = new BiTNode;  //生成根节点
        T->data = ch;  //根节点数据域置为ch
        CreateBiTree(T->lchild);  //递归创建左子树
        CreateBiTree(T->rchild);  //递归创建右子树
    }  //else
}
复制二叉树
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;
}
完整代码 from WalkingWithTheWind~
#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]
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞b6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值