以下是本人在学习数据结构与算法时的笔记 //数据结构与算法基础 ------------------------------------------------------- 链表 struct Ploy{ int m_coe = 0; int m_index = 0; }; typedef struct LNode{ Ploy date; LNode *prior = NULL; LNode *next = NULL; }LNode,*LinkList; //建立链表 void setLinkList(LinkList &L){ LNode *p,*q; q = L; int coe,index,n; cout << "输入n:"; cin >> n; while (n--){ cin>>coe>>index; if (index<0) break; p = new LNode; p->date.m_coe = coe; p->date.m_index = index; q->next = p; q = q->next; } } //合并链表 void combine(LinkList &L,LinkList &S,LinkList &T){ LNode *p,*q,*r; p = L->next,q = S->next,r = T; while (p && q){ if (p->date.m_index < q->date.m_index){ r ->next= p; p = p->next; r = r->next; }else if (p->date.m_index > q->date.m_index){ r ->next= q; q = q->next; r = r->next; }else{ p->date.m_coe+=q->date.m_coe; if (p->date.m_coe==0){ LNode *s,*t; s = p,t = q; p = p->next; q = q->next; delete s; delete t; }else { r->next = p; LNode *s; s = q; q = q->next; p = p->next; r = r->next; delete s; } } } r->next= p?p:q; delete S; S = NULL; } //打印链表 void printLinkList(LinkList &L){ LNode *p; p = L->next; while (p){ cout<<p->date.m_coe<<" "<<p->date.m_index<<" "; p = p->next; } } //尾指针循环链表 void CircleLinkList(LinkList &L){ LNode *p,*q; q = L; int n; cout <<"输入尾指针循环链表长度n:"; cin >> n; while (n--){ p = new LNode; cin >> p->date.m_coe >> p->date.m_index; q->next = p; q = p; } q->next = L; L = q; } //循环链表合并 void CombineCircleLinkList(LinkList &L,LinkList &S){ LNode *r; r = L->next; L->next = S->next->next; S->next = r; delete S->next; } //双向链表 void DoLinkList(LinkList &L){ LNode *p,*q; q = L; q->prior = NULL; int n; cout << "输入双向链表的长度n:"; cin >> n; while (n--){ p = new LNode; cin >> p->date.m_coe >> p->date.m_index; p->prior = q; q->next = p; q = p; } //循环双向链表 // q->next = L; // L->prior = q; } //------------------------------------------------------ //顺序栈 #define MAXSIZE 100 typedef struct { int *base = NULL; int *top = NULL; int stackSize = 0; }SqStack; //初始化空栈 void initStack(SqStack &S){ S.base = new int[MAXSIZE]; if(S.base == NULL){ cout <<"内存分配失败!"<<endl; exit(-1); } S.top = S.base; S.stackSize = MAXSIZE; } //判断栈是否为空,空则返回1,否则返回0; int StackEmpty(SqStack &S){ return S.base==S.top; } //栈的长度 int StackLength(SqStack &S){ return S.top-S.base; } //清空栈 void ClearStack(SqStack &S){ if (S.base) S.top = S.base; } //销毁栈 void DestroyStack(SqStack &S){ if (S.base){ delete []S.base; S.stackSize = 0; S.base = S.top = NULL; } } //入栈 void Push(SqStack &S,int e){ if (S.top-S.base == S.stackSize){ cout<< "栈已满"<<endl; exit(-1); } *S.top++ = e; } //出栈 void Pop(SqStack &S,int &e){ if (S.top==S.base){ cout <<"栈已空"<<endl; exit(-1); } e = *--S.top; } //--------------------------------------------------- //链栈 运算受限的链表 只能在链表头部操作 typedef struct StackNode{ int date; StackNode *next; }StackNode,*LinkStack; //链栈初始化 void initLinkStack(LinkStack &S){ S = NULL; } //判断链栈是否为空 int StackEmpty(LinkStack &S){ return S==NULL; } //链栈的入栈 void Push(LinkStack &S,int e){ StackNode *p; p = new StackNode; p->date = e; p->next = S; S = p; } //链栈的出栈 void Pop(LinkStack &S,int &e){ if (S == NULL){ cout << "链栈已空,无法出栈"<<endl; exit(-1); } StackNode *p; e = S->date; p = S; S = S->next; delete p; } //取栈顶元素 int GetTop(LinkStack &S){ if (S==NULL){ cout << "栈为空"<<endl; exit(-1); }else return S->date; } //-------------------------------------------------------------- //循环队列 #define QUEUEMAXSIZE 100 struct SqQueue{ int *base = NULL; int front = 0; int rear = 0; }; //初始化队列 void initQueue(SqQueue &Q){ Q.base = new int[QUEUEMAXSIZE]; if (Q.base==NULL){ cout<<"内存分配失败"<<endl; exit(-1); } Q.front = Q.rear = 0; } //判断队是否为空 int QueueEmpty(SqQueue &Q){ return Q.front==Q.rear; } //求队列长度 int QLength(SqQueue &Q){ return (Q.rear-Q.front+QUEUEMAXSIZE)%QUEUEMAXSIZE; } //循环队列入队 void EnQueue(SqQueue &Q,int e){ if ((Q.rear+1)%QUEUEMAXSIZE == Q.front){ cout << "队列已满,入队失败"<< endl; exit(-1); } Q.base[Q.rear] = e; Q.rear = (Q.rear+1)%QUEUEMAXSIZE; } //循环队列出队 void DeQueue(SqQueue &Q,int &e) { if (Q.front == Q.rear) { cout << "队列已空,出队失败" << endl; exit(-1); } e = Q.base[Q.front]; Q.front = (Q.front + 1) % QUEUEMAXSIZE; } //取循环队列首元素 int GetHead(SqQueue &Q){ if (Q.front == Q.rear){ cout << "队列已空,取首元素失败" << endl; } return Q.base[Q.front]; } //--------------------------------------------------------- //链队 typedef struct QNode{ int date = 0; QNode *next = NULL; }QNode,*QueuePtr; //链队头指针 尾指针 typedef struct{ QueuePtr front = NULL; QueuePtr rear = NULL; }LinkQueue; //初始化链队 void initLinkQueue(LinkQueue &Q){ Q.front = Q.rear = new QNode; if (Q.front == NULL){ cout << "内存分配失败" << endl; exit(-1); } Q.front->next = NULL; } //销毁链队 void DestroyLinkQueue(LinkQueue &Q){ while (Q.front){ Q.rear = Q.front->next; delete Q.front; Q.front = Q.rear; } } //入队 void EnLinkQueue(LinkQueue &Q,int e){ QNode *p; p = new QNode; if (p == NULL){ cout << "内存分配失败" << endl; exit(-1); } p->date = e; p->next = NULL; Q.rear->next= p; Q.rear = p; } //出对 void DeLinkQueue(LinkQueue &Q,int &e){ if (Q.front == Q.rear){ cout << "队列已空,出队失败" << endl; exit(-1); } QNode *p; p = Q.front->next; e = p->date; Q.front->next = p->next; if (p == Q.rear) Q.rear = Q.front; //删除的是最后节点 delete p; } //取队列首元素 void GetHead(LinkQueue &Q,int &e){ if (Q.front == Q.rear){ cout << "队列已空,取元失败" << endl; exit(-1); } e = Q.front->next->date; } //--------------------------------------------------------------- //串 //串的顺序储存结构 #define MAXLENGTH 255 typedef struct{ char ch[MAXLENGTH+1]; int length; }SString; //串的链式储存结构--块链 #define CHUNKSIZE 80 typedef struct Chunk{ char ch[CHUNKSIZE]; struct Chunk *next; }Chunk; typedef struct{ Chunk *head,*tail; int curlen; //串的当前长度 }LString; //BF算法----暴力穷举法 int Index_BF(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; } //KMP算法 void get_next(SString T,int next[]){ int i=1,j=0; next[1]=0; while (i<T.length){ if (j==0 || T.ch[i]==T.ch[j]){ ++i,++j; next[i]=j; }else j = next[j]; } } int Index_KMP(SString S,SString T,int pos,const int next[]){ int i=pos,j=1; //pos 开始匹配位置 while (i<=S.length && j<=T.length){ if (j==0 || S.ch[i]==T.ch[j]) i++,j++; else j = next[j]; //i不变,j后退 } if (j>T.length) return i-T.length; else return 0; } //-------------------------------------------------------------------- //二叉树 //总边数为 B B = n-1 = n2*2+n1*1 // n = n2*2+n1*1+1 又 n = n2+n1+n0 //即n0 = n2+1 叶子数目为度为2的结点数+1 //二叉树顺序储存表示 typedef int SqBiTree[MAXSIZE]; SqBiTree bt; //二叉树链表储存结构 typedef struct BTNode{ int data; BTNode *LChild,*RChild;//*parent }BTNode,*BiTree; //遍历二叉树 void visit(BiTree &T){ cout << T->data; } //先序 DLR 递归 void PreOrderTraverse(BiTree &T){ if(T==NULL) return; else{ visit(T); PreOrderTraverse(T->LChild); PreOrderTraverse(T->RChild); } } //中序 非递归 void InOrderTraverse(BiTree T){ SqStack S; BiTree p,q; initStack(S); p = T; while (p || !StackEmpty(S)){ if (p){ Push(S,p); //入栈 p = p->LChild; }else{ Pop(S,q); //出栈 cout << q->data; p = q->RChild; } } } //层次遍历 typedef struct{ BTNode data[MAXSIZE]; int front,rear; }TreeSqQueue; void LevelOrder(BTNode *b){ BTNode *p; TreeSqQueue *qu; initQueue(qu); //初始化队列 EnQueue(qu,b); //根结点指针进入队列 while (!QueueEmpty(qu)) { //队不为空,则循环 DeQueue(qu, p); //出队结点p cout << p->data; if (p->LChild != NULL) EnQueue(qu, p->LChild); if (p->RChild != NULL) EnQueue(qu, p->RChild); } } //建立二叉树 // A // B // C D // E F // G //ABC##DE#G##F### void CreateBiTree(BiTree &T){ char ch; cin>>ch; if (ch == '#') T = NULL; else{ if (!(T = new BTNode)) exit(-1); T->data = ch; CreateBiTree(T->LChild); CreateBiTree(T->RChild); } } //复制二叉树 int Copy(BiTree T,BiTree &NewT){ if (T==NULL){ NewT = NULL; return 0; //如果是空树返回0 }else{ NewT = new BTNode; NewT->data = T->data; Copy(T->LChild,NewT->LChild); Copy(T->LChild,NewT->RChild); return 1; } } //计算二叉树深度 //n个结点时间复杂度为log2N+1 //左子树深度 m 与 右子树深度 n 的较大者 +1 int Depth(BiTree T){ int m,n; if (T==NULL) return 0; else { m = Depth(T->LChild); n = Depth(T->RChild); return max(m,n)+1; } } //计算二叉树结点 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; else if (T->LChild==NULL && T->RChild==NULL) return 1; else return LeadCount(T->LChild)+LeadCount(T->RChild); } //线索二叉树 //LTag(RTag) == 0 指向该结点的左(右)孩子 // 1 前驱(后继) typedef struct BiThrNode{ int data; int LTag,RTag; BiThrNode *LChild,*RChild; }BiThrNode,*BiThrTree; //可增设一个头结点 //其LTag = 0,LChild指向根结点 //其RTag = 0,RChild指向遍历序列中最后一个结点 //遍历序列中第一个结点的LC域和最后一个结点的RC域都指向头结点 //------------------------------------------------------------ //树 //双亲表示法 //每个结点两个域 数据域 双亲域(双亲结点在数组中的位置) typedef struct PTNode{ int data; int parent; } PTNode; #define MAX_TREE_SIZE 100 typedef struct{ PTNode nodes[MAX_TREE_SIZE]; int r,n; //根结点位置和结点个数; } PTree; //孩子链表 //孩子结点结构 typedef struct CTNode{ int child; CTNode *next; } *ChildPtr; //双亲结点结构 typedef struct{ int data; ChildPtr firstChild; //孩子链表头指针 } CTBox; //树结构 typedef struct { CTBox nodex[MAX_TREE_SIZE]; int n,r; }CTree; //可增加双亲域 //孩子兄弟表示法(二叉树表示法,二叉树链表表示法) typedef struct CSNode{ int data; CSNode *firstChild,*nextSibling; } CSNode,*CSTree; //将树转换为二叉树 //兄弟相连留长子 去掉原来右孩线 //森林转换为二叉树 //树变二叉根相连 //------------------------------------- //哈夫曼树(最优二叉树):带权路径长度(WPL)最短的二叉树 //权:树中结点的数值 //结点的带权路径长度:根到该结点的 路径长度 与该结点的 权 的乘积 //数的带权路径长度:树中所有叶子结点的带权路径长度之和 //构造哈夫曼树:1、构造森林全是根 2、选用两小造新树 // 3、删除两小添新人 4、重复2、3剩单根 //哈夫曼构造算法的实现 采用顺序储存结构 共2n-1个结点 typedef struct{ int weight; int parent,lch,rch; } HTNode,*HuffmanTree; //构造哈夫曼树 void select(HuffmanTree &HT,int len,int &s1,int &s2){ } void CreatHuffmanTree (HuffmanTree &HT,int n){ if (n<=1) return; int m = 2*n-1; HT = new HTNode[m+1]; //0号单元未用 HT[m]表示根结点 for (int i = 1; i <= m; ++i) { HT[i].lch = 0; HT[i].rch = 0; HT[i].parent = 0; } for (int i = 1; i <= n; ++i) { cin >> HT[i].weight; //输入权 } int s1,s2; for (int i = n+1; i <= m; ++i) { select(HT,i-1,s1,s2); //寻找两个最小结点的下标 HT[s1].parent = HT[s2].parent = i; HT[i].lch = s1,HT[i].rch = s2; HT[i].weight = HT[s1].weight + HT[s2].weight; } } //哈夫曼编码 typedef struct HuffmanCode{ char data; char *code; }*pHuffmanCode; void CreatHuffmanCode(HuffmanTree HT,pHuffmanCode &HC,int n){ HC = new HuffmanCode[n+1]; char *cd; cd = new char[n]; for (int i = 1; i <= n; ++i) { int start = 0,c = i,f = HT[i].parent; while (f!=0){ start++; if (HT[i].lch == c) cd[start] = '0'; else cd[start] = '1'; c = f,f = HT[f].parent; } cd[++start] = '\0'; strrev(cd); //反转编码 HC[i].code = new char[start]; strcpy(HC[i].code,cd); } delete cd; } //----------------------------------------------------------------------- //图 //邻接矩阵 #define MaxInt 32767 //表示极大值,即∞ #define MVNum 100 //最大顶点数 typedef struct{ char vex[MVNum]; //顶点表 int arcs[MVNum][MVNum]; //邻接矩阵 int vexNum,arcNum; //图的当前点数和边数 } AMGraph; //创建无向网 int LocateVex(AMGraph &G,char v){ for (int i = 0; i < G.vexNum; ++i) { if (G.vex[i] == v) return i; } return -1; } void CreateUDM(AMGraph &G){ cin >> G.vexNum >> G.arcNum; //总点数 总边数 for (int i = 0; i < G.vexNum; ++i) { cin >> G.vex[i]; //输入点的信息 } for (int i = 0; i < G.vexNum; ++i) { for (int j = 0; j < G.vexNum; ++j) { G.arcs[i][j] = MaxInt; //所有边的权置为极大值 } } char v1,v2; int w; for (int k = 0; k < G.arcNum; ++k) { cin >> v1 >> v2 >> w; //一条边的两个顶点及边的权值 int i = LocateVex(G,v1); int j = LocateVex(G,v2); G.arcs[i][j] = w; G.arcs[j][i] = G.arcs[i][j]; } } //------------------------------------------------------------ //邻接表 struct ArcNode{ //边结点 int adjVex; //该边所指向的顶点的位置 ArcNode *nextArc; //指向下一条边的指针 int info; //和边相关的信息 }; typedef struct VNode{ char data; //顶点信息 ArcNode *firstArc; //指向第一条依附该顶点的边的指针 } VNode,AdjList[MVNum]; typedef struct{ AdjList vertices; int vexNum,arcNum; } ALGraph; //创建无向网 int LocateVex(ALGraph &G,char v){ for (int i = 0; i < G.vexNum; ++i) { if (G.vertices[i].data == v) return i; } return -1; } void CreateUDG(ALGraph &G){ cin >> G.vexNum >>G.arcNum; for (int i = 0; i < G.vexNum; ++i) { cin >> G.vertices[i].data; G.vertices[i].firstArc = NULL; } char v1,v2; for (int k = 0; k < G.arcNum; ++k) { cin >> v1 >> v2; int i = LocateVex(G,v1); int j = LocateVex(G,v2); ArcNode *p1,*p2; p1 = new ArcNode; p1->adjVex = j; p1->nextArc = G.vertices[i].firstArc; //头插法 G.vertices[i].firstArc = p1; p2 = new ArcNode; p2->adjVex = i; p2->nextArc = G.vertices[j].firstArc; G.vertices[j].firstArc = p2; } } //邻接矩阵多用于稠密图 邻接表多用于稀疏图 //采用 邻接矩阵 表示图的 深度优先 搜索遍历 int visited[100]; //第i个顶点已访问则 visited[i] = 1;否则为0; void DFS(AMGraph G,int v){ cout << v; visited[v] = true; for (int w = 0; w < G.vexNum; ++w) { if (G.arcs[v][w]!=0 && visited[w]==0){ //w是v的邻接点且w为2访问 DFS(G,w); } } } //广度优先 int FirstAdjVex(ALGraph G,int u){ return G.vertices[u].firstArc->adjVex; } int NextAdjVex(ALGraph G,int u,int w){ ArcNode *p; p = G.vertices[u].firstArc; while (w != p->adjVex){ p = p->nextArc; } if (p->nextArc == NULL) return -1; else return p->nextArc->adjVex; } void BFS(ALGraph G,int v){ cout << v; visited[v] = true; SqQueue Q; initQueue(Q); EnQueue(Q,v); int u; while (!QueueEmpty(Q)){ DeQueue(Q,u); for (int w = FirstAdjVex(G,u); w >= 0; w = NextAdjVex(G,u,w)) { if (visited[w]==0){ cout << w; visited[w] = true; EnQueue(Q,w); } } } }
数据结构与算法基础笔记
这篇笔记详细介绍了数据结构中的链表、顺序栈、链栈、循环队列、双向链表等操作,包括创建、合并、遍历和删除等。此外,还涵盖了二叉树的各种遍历方法以及哈夫曼树的构造。同时,讲解了图的邻接矩阵和邻接表表示,并实现了深度优先搜索和广度优先搜索。这些内容对于理解数据结构与算法的基础至关重要。
摘要由CSDN通过智能技术生成