├── CONTRIBUTING.md ├── search ├── binary_search.exe └── binary_search.cpp ├── string ├── compare_string.exe ├── compare_string.cpp └── kmp.cpp ├── sort ├── sq_list.cpp └── bubble_sort.cpp ├── linear_list ├── sq_stack.cpp ├── sq_queue.cpp ├── link_queue.cpp ├── link_stack.cpp ├── sq_double_stack.cpp └── link_list.cpp ├── tree ├── tree_struct.cpp └── bi_tree.cpp ├── graph ├── dfs.cpp ├── m_graph.cpp ├── dfs_adj_list.cpp └── graph_adj_list.cpp ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md └── README.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /search/binary_search.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nate-yu/data-structure-study/HEAD/search/binary_search.exe -------------------------------------------------------------------------------- /string/compare_string.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nate-yu/data-structure-study/HEAD/string/compare_string.exe -------------------------------------------------------------------------------- /sort/sq_list.cpp: -------------------------------------------------------------------------------- 1 | #define MAXSIZE 10 2 | typedef struct 3 | { 4 | int r[MAXSIZE+1]; // 用于存储要排序的数组,r[0]用作哨兵或临时变量 5 | int length; // 记录顺序表的长度 6 | }SqList; 7 | 8 | /*交换L中数组r的下标为i和j的值*/ 9 | void swap(SqList *L,int i,int j) { 10 | int temp = L->r[i]; 11 | L->r[i] = L->r[j]; 12 | L->r[j] = temp; 13 | } -------------------------------------------------------------------------------- /search/binary_search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | /* 8 | * 二分查找 9 | * @param *a 查找数组 10 | * @param n 数组长度 11 | * @param key 查找的值 12 | */ 13 | int Binary_Search(int *a, int n, int key) { 14 | int low,high,mid; 15 | low = 1; 16 | high = n; 17 | while(low <= high) { 18 | mid = (low + high) / 2; 19 | if(key < a[mid]) { 20 | high = mid - 1; 21 | } else if(key > a[mid]) { 22 | low = mid + 1; 23 | } else { 24 | return mid; 25 | } 26 | } 27 | return 0; 28 | } 29 | 30 | int main() 31 | { 32 | int array[11] = {0,1,16,24,35,47,59,62,73,88,99}; 33 | cout<< Binary_Search(array,11,62) << endl; 34 | return 0; 35 | } -------------------------------------------------------------------------------- /linear_list/sq_stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef int SElementType; 8 | typedef MAXSIZE 100; 9 | 10 | /*栈的顺序存储结构*/ 11 | typedef struct 12 | { 13 | SElementType data[MAXSIZE]; 14 | int top; 15 | }SqStack; 16 | 17 | /*插入元素e作为新的栈顶元素*/ 18 | bool Push(SqStack *S, SElementType e) { 19 | if(S->top == MAXSIZE - 1){ // 栈满 20 | return false; 21 | } 22 | S->top++; 23 | S->data[S->top] = e; 24 | return true; 25 | } 26 | 27 | /*若栈不为空,则删除S的栈顶元素,用e返回其值,并返回true;否则返回false*/ 28 | bool Pop(SqStack *S, SElementType *e) { 29 | if(S->top == -1){ // 空栈 30 | return false; 31 | } 32 | *e = S->data[top] 33 | S->top--; 34 | return true; 35 | } -------------------------------------------------------------------------------- /tree/tree_struct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | #define MAX_TREE_SIZE 100 5 | 6 | 7 | /*树的双亲表示法结点结构定义*/ 8 | 9 | /*结点结构*/ 10 | typedef struct PNode 11 | { 12 | int data; // 结点数据 13 | int parent; // 双亲位置 14 | }PTNode; 15 | 16 | /*树结构*/ 17 | typedef struct 18 | { 19 | PTNode nodes[MAX_TREE_SIZE]; // 结点数组 20 | int r,n; // 根的位置和结点数 21 | }PTree; 22 | 23 | /*树的孩子表示法结构定义*/ 24 | 25 | /*孩子结点*/ 26 | typedef struct CTNode 27 | { 28 | int child; 29 | struct CTNode *next; 30 | } *ChildPtr; 31 | 32 | /*表头结构*/ 33 | typedef struct 34 | { 35 | int data; 36 | ChildPtr firstchild; 37 | }CTBox; 38 | 39 | /*树结构*/ 40 | typedef struct 41 | { 42 | CTBox nodes[MAX_TREE_SIZE]; // 结点数组 43 | int r,n; // 根的位置和结点数 44 | }CTree; 45 | 46 | -------------------------------------------------------------------------------- /graph/dfs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | /*图的存储结构*/ 6 | typedef struct 7 | { 8 | char vexs[100]; // 顶点表 9 | int arc[100][100]; // 邻接矩阵,可以看作边表 10 | int numVertexes,numEdges; // 图中的顶点数和边数 11 | }MGraph; 12 | 13 | bool visited[100]; // 访问标志的数组 14 | 15 | /*邻接矩阵的深度优先递归算法*/ 16 | void DFS(MGraph G, int i) { 17 | int j; 18 | visited[i] = true; 19 | cout< 2 | 3 | using namespace std; 4 | 5 | /*图的存储结构*/ 6 | typedef struct 7 | { 8 | char vexs[100]; // 顶点表 9 | int arc[100][100]; // 邻接矩阵,可以看作边表 10 | int numVertexes,numEdges; // 图中的顶点数和边数 11 | }MGraph; 12 | 13 | /*建立无向网图的邻接矩阵表示*/ 14 | void CreateMGraph(MGraph *G) { 15 | int i,j,k,w; 16 | cout<<"please input the numVertexes and numEdges: "<>G->numVertexes>>G->numEdges; 18 | // 读入顶点信息,建立顶点表 19 | for (i = 0; i < G->numVertexes; ++i) 20 | { 21 | cin>>G->vexs[i]; 22 | } 23 | for (i = 0; i < G->numVertexes; ++i) 24 | { 25 | for (j = 0; i < numVertexes; ++j) 26 | { 27 | // 邻接矩阵初始化 28 | G->arc[i][j] = 65535; 29 | } 30 | } 31 | 32 | for(k = 0; k < G->numEdges; k++) { 33 | cout<<"please input edge's (vi,vj) and weight w: "<>i>>j>>w; 35 | G->arc[i][j] = w; 36 | G->arc[i][j] = G->arc[j][i]; // 无向图对称 37 | } 38 | } -------------------------------------------------------------------------------- /string/compare_string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | string s; 6 | 7 | int StrLength(string S) { 8 | return S.length(); 9 | } 10 | 11 | void SubString(string S, int pos, int len) { 12 | s = S.substr(pos,len); 13 | } 14 | 15 | int StrCompare(string sub, string T) { 16 | return sub.compare(T); 17 | } 18 | 19 | /* 20 | * T为非空串,若主串S中第pos个字符之后存在与T相等的字串, 21 | * 则返回第一个这样的字串在S中的位置,否则返回0 22 | */ 23 | int Index(string S, string T, int pos) { 24 | int n,m,i; 25 | if (pos > 0) 26 | { 27 | n = StrLength(S); 28 | m = StrLength(T); 29 | i = pos; 30 | while(i <= n-m+1) { 31 | SubString(S,i,m); // 取主串第i个位置长度与T相等的字串给s 32 | if(StrCompare(s,T) != 0) { 33 | ++i; 34 | } 35 | else { 36 | return i; 37 | } 38 | } 39 | } 40 | return 0; 41 | } 42 | 43 | 44 | int main() 45 | { 46 | string S,T; 47 | int pos; 48 | cout<< "input S,T,pos: "<>S>>T>>pos 50 | cout< 2 | #include 3 | using namespace std; 4 | 5 | typedef int QElementType; 6 | typedef MAXSIZE 100; 7 | 8 | // 循环队列的顺序存储结构 9 | typedef struct 10 | { 11 | QElementType data[MAXSIZE]; 12 | int font; // 头指针 13 | int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置 14 | }SqQueue; 15 | 16 | /*初始化一个空队列*/ 17 | bool InitQueue(SqQueue *Q) { 18 | Q -> font = 0; 19 | Q -> rear = 0; 20 | return true; 21 | } 22 | 23 | /*求队列的长度*/ 24 | int QueueLength(SqQueue Q) { 25 | return (Q.rear-Q.font+MAXSIZE) % MAXSIZE; 26 | } 27 | 28 | /*若队列未满,则插入元素e作为新的队列元素*/ 29 | bool EnQueue(SqQueue *Q, QElementType e) { 30 | if ((Q->rear+1) % MAXSIZE == Q->font) // 队列满的判断 31 | { 32 | return false; 33 | } 34 | 35 | Q->data[Q->rear] = e; // 将e赋值给对尾 36 | Q->rear = (Q->rear + 1) % MAXSIZE; // rear指针向后移动一位 37 | 38 | return true; 39 | } 40 | 41 | /*若队列不空,则删除对头元素,用e返回*/ 42 | bool DeQueue(SqQueue *Q, QElementType *e) { 43 | if (Q->font == Q->rear) // 判断队列是否为空 44 | { 45 | return false; 46 | } 47 | 48 | *e = Q->data[Q->font]; 49 | Q->font = (Q->font+1) % MAXSIZE; 50 | return true; 51 | } -------------------------------------------------------------------------------- /linear_list/link_queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef int QElementType; 8 | typedef MAXSIZE 100; 9 | 10 | // 结点结构 11 | typedef struct QNode 12 | { 13 | QElementType data; 14 | struct QNode *next; 15 | }QNode, *QueuePtr; 16 | 17 | // 队列的链表结构 18 | typedef struct 19 | { 20 | QueuePtr font,rear; // 对尾指针 21 | }LinkQueue; 22 | 23 | /*入队操作*/ 24 | bool EnQueue(LinkQueue *Q, QElementType e) { 25 | QueuePtr s = (QueuePtr) malloc (sizeof(QNode)); 26 | if (!s) // 存储分配失败 27 | { 28 | exit(OVERFLOW); 29 | return false; 30 | } 31 | s->data = e; 32 | s->next = NULL; 33 | 34 | Q->rear->next = s; // 把拥有e的新结点s赋值给原队尾结点的后继 35 | Q->rear = s; // 把当前的s设置尾队尾结点,rear指针指向s 36 | return true; 37 | } 38 | 39 | /*出队操作*/ 40 | bool DeQueue(LinkQueue *Q, QElementType e) { 41 | QueuePtr p; 42 | if(Q->font == Q->rear) 43 | return false; 44 | p = Q->font->next; // 将欲删除的队头结点暂存给p 45 | *e = p->data; 46 | Q->font->next = p->next; // 将原队头结点后继p->next赋值给头结点后继 47 | if(Q->rear == p) // 若队头是队尾,则删除后将rear指向头结点 48 | Q->rear = Q->font; 49 | free(p); 50 | return true; 51 | } -------------------------------------------------------------------------------- /linear_list/link_stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef int SElementType; 8 | typedef MAXSIZE 100; 9 | 10 | typedef struct StackNode 11 | { 12 | SElementType data; 13 | struct StackNode *next; 14 | }StackNode,*LinkStackPtr; // 声明结点时用StackNode,声明指针时用LinkStackPtr 15 | 16 | typedef struct LinkStack 17 | { 18 | LinkStackPtr top; 19 | int count; 20 | }LinkStack; 21 | 22 | /*插入元素e为新的栈顶元素*/ 23 | bool Push(LinkStack *S, SElementType e) { 24 | LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode)); 25 | s->data = e; 26 | s->next = S->top; // 把当前的栈顶元素赋值给新结点的直接后继 27 | S->top = s; // 将新结点s赋值给栈顶指针 28 | S->count++; 29 | return true; 30 | } 31 | 32 | /*若栈不为空,则删除栈顶元素*/ 33 | bool Push(LinkStack *S, SElementType e) { 34 | LinkStackPtr p; 35 | if (StackEmpty(*S)) 36 | { 37 | return false; 38 | } 39 | *e = S->top->data; 40 | p = S->top; // 将栈顶元素赋值给p 41 | S->top = S->top->next; // 使得栈顶指针下移一位,指向后一结点 42 | free(p); 43 | S->count--; 44 | return true; 45 | } 46 | 47 | bool StackEmpty(LinkStack *S) { 48 | if(S->top != null) { 49 | return false; 50 | } 51 | return true; 52 | } -------------------------------------------------------------------------------- /linear_list/sq_double_stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef int SElementType; 8 | typedef MAXSIZE 100; 9 | 10 | /*两栈共享空间结构*/ 11 | typedef struct 12 | { 13 | SElementType data[MAXSIZE]; 14 | int top1; // 栈1栈顶指针 15 | int top2; // 栈2栈顶指针 16 | }SqDoubleStack; 17 | 18 | /*将元素e压入栈*/ 19 | bool Push(SqDoubleStack *S, SElementType e, int stackNumber) { 20 | // 栈满,无法添加新元素 21 | if(S->top1 + 1== S -> top2) { 22 | return false; 23 | } 24 | // 栈1有元素进栈 25 | if(stackNumber == 1) { 26 | S->data[++S->top1] = e; // 若栈1则先top1+1后给数组元素赋值 27 | } 28 | // 栈2有元素进栈 29 | else if(stackNumber == 2) { 30 | S->data[--S->top2] = e; // 若栈2则先top2-1后给数组元素赋值 31 | } 32 | return true; 33 | } 34 | 35 | /*若栈不空,则删除S的栈顶元素,用e返回其值*/ 36 | bool Pop(SqDoubleStack *S, SElementType *e, int stackNumber) { 37 | if (stackNumber == 1) 38 | { 39 | if(S->top1 == -1) { // 说明栈1已经是空栈,溢出 40 | return false; 41 | } 42 | *e = S->data[S->top1--]; // 将栈1的栈顶元素出栈 43 | } 44 | else if(stackNumber == 2) { 45 | if(S->top2 = MAXSIZE) { // 说明栈2已经是空栈,溢出 46 | return false; 47 | } 48 | *e = S->data[S->top2++]; 49 | } 50 | return true; 51 | } -------------------------------------------------------------------------------- /sort/bubble_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | #define MAXSIZE 10 7 | typedef struct 8 | { 9 | int r[MAXSIZE+1]; // 用于存储要排序的数组,r[0]用作哨兵或临时变量 10 | int length; // 记录顺序表的长度 11 | }SqList; 12 | 13 | /*交换L中数组r的下标为i和j的值*/ 14 | void swap(SqList *L,int i,int j) { 15 | int temp = L->r[i]; 16 | L->r[i] = L->r[j]; 17 | L->r[j] = temp; 18 | } 19 | 20 | /*初级冒泡*/ 21 | void BubbleSort0(SqList *L) { 22 | for(int i = 1; i < L->length; i++) { 23 | for(int j = i+1; j <= L->length; j++) { 24 | if (L->r[i] > L->r[j]) 25 | { 26 | swap(L,i,j); 27 | } 28 | } 29 | } 30 | } 31 | 32 | /*正版冒泡*/ 33 | void BubbleSort(SqList *L) { 34 | for(int i = 1; i < L->length; i++) { 35 | for(int j = L->length-1; j >= i; j++) { 36 | if (L->r[j] > L->r[j+1]) 37 | { 38 | swap(L,j,j+1); 39 | } 40 | } 41 | } 42 | } 43 | 44 | /*优化冒泡*/ 45 | void BubbleSort2(SqList *L) { 46 | bool flag = true; 47 | for(int i = 1; i < L->length && flag; i++) { //若flag为ture则退出循环 48 | flag = false; // 初始为false 49 | for(int j = L->length-1; j >= i; j++) { 50 | if (L->r[j] > L->r[j+1]) 51 | { 52 | swap(L,j,j+1); 53 | flag = true; // 若有数据交换,则flag为ture 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /graph/dfs_adj_list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | /*边表结点*/ 7 | typedef struct EdgeNode 8 | { 9 | int adjvex; // 邻接点域,存储该顶点对应的下标 10 | int weight; // 用于存储权值 11 | struct EdgeNode *next; // 链域,用于指向下一个 邻接点 12 | }EdgeNode; 13 | 14 | /*顶点表结点*/ 15 | typedef struct VertexNode 16 | { 17 | char data; // 顶点域,用于存储顶点信息 18 | EdgeNode *firstedge; // 边表头指针 19 | }VertexNode,AdjList[100]; 20 | 21 | /*无向图的邻接表存储结构*/ 22 | typedef struct 23 | { 24 | AdjList adjList; 25 | int numVertexes,numEdges; // 图中当前顶点数和边数 26 | }GraphAdjList; 27 | 28 | bool visited[100]; // 访问标志的数组 29 | 30 | /*邻接表的深度优先递归算法*/ 31 | void DFS(GraphAdjList GL,int i) { 32 | EdgeNode *p; 33 | visited[i] = true; 34 | cout<adjList[i].data; 35 | 36 | p = GL->adjList[i].firstedge; 37 | while(p){ 38 | if(!visited[p->adjvex]) { 39 | DFS(GL, p->adjvex); // 对未访问的邻接顶点递归调用 40 | } 41 | p = p->next; 42 | } 43 | 44 | } 45 | 46 | /*邻接表的深度遍历操作*/ 47 | void DFSTraverse(GraphAdjList GL) { 48 | int i; 49 | for(i = 0; i < GL->numVertexes; i++) { 50 | visited[i] = false; // 初始化所有顶点状态都是未访问过状态 51 | } 52 | for(i = 0; i < GL->numVertexes; i++) { 53 | // 对未访问过的顶点调用DFS,若是连通图则只会执行一次 54 | if(!visited[i]) { 55 | DFS(GL,i); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /tree/bi_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | /*二叉树的二叉链表结点结构定义*/ 7 | typedef struct BiTNode 8 | { 9 | char data; 10 | struct BiTNode *lchild, *rchild; 11 | }BiTNode, *BiTree; 12 | 13 | /* 14 | * 二叉树的前序遍历递归算法 15 | * 从根节点出发,先左后右 16 | */ 17 | void PreOrderTraverse(BiTree T) { 18 | if(T == NULL) { 19 | return; 20 | } 21 | cout<data<<" "; // 显示结点数据 22 | PreOrderTraverse(T->lchild); // 再先序遍历左子树 23 | PreOrderTraverse(T->rchild); // 最后先序遍历右子树 24 | } 25 | 26 | /* 27 | * 二叉树的中序遍历递归算法 28 | * 左子树优先,有左则左,无左则右 29 | */ 30 | void InOrderTraverse(BiTree T) { 31 | if(T == NULL) { 32 | return; 33 | } 34 | InOrderTraverse(T->lchild); // 中序遍历左子树 35 | cout<data<<" "; // 显示结点数据 36 | InOrderTraverse(T->rchild); // 最后中序遍历右子树 37 | } 38 | 39 | /* 40 | * 二叉树的中序遍历递归算法 41 | * 从左到右,先叶子后结点 42 | */ 43 | void PostOrderTraverse(BiTree T) { 44 | if(T == NULL) { 45 | return; 46 | } 47 | PostOrderTraverse(T->lchild); // 先后序遍历左子树 48 | PostOrderTraverse(T->rchild); // 再后序遍历右子树 49 | cout<data<<" "; // 显示结点数据 50 | } 51 | 52 | /* 53 | * 按前序输入二叉树中结点的值 54 | * #表示空树,构造二叉链表表示二叉树T 55 | */ 56 | void CreateBiTree(BiTree *T) { 57 | char ch; 58 | cin>>ch; 59 | if (ch == '#') 60 | *T == NULL; 61 | else { 62 | *T = (BiTree) malloc (sizeof(BiTNode)); 63 | (*T)->data = ch; 64 | CreateBiTree(&(*T) -> lchild); // 构造左子树 65 | CreateBiTree(&(*T) -> rchild); // 构造右子树 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /graph/graph_adj_list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | /*边表结点*/ 7 | typedef struct EdgeNode 8 | { 9 | int adjvex; // 邻接点域,存储该顶点对应的下标 10 | int weight; // 用于存储权值 11 | struct int *next; // 链域,用于指向下一个 邻接点 12 | }EdgeNode; 13 | 14 | /*顶点表结点*/ 15 | typedef struct VertexNode 16 | { 17 | char data; // 顶点域,用于存储顶点信息 18 | EdgeNode *firstedge; // 边表头指针 19 | }VertexNode,AdjList[100]; 20 | 21 | /*无向图的邻接表存储结构*/ 22 | typedef struct 23 | { 24 | AdjList adjList; 25 | int numVertexes,numEdges; // 图中当前顶点数和边数 26 | }GraphAdjList; 27 | 28 | /*建立图的邻接表结构*/ 29 | void CreateALGraph(GraphAdjList *G) { 30 | int i,j,k; 31 | EdgeNode *e; 32 | cout<<"please input numVertexes and numEdges: "<>G->numVertexes>>G->numEdges; 34 | // 读取顶点信息,建立顶点表 35 | for(i = 0; i < G->numVertexes; i++) { 36 | cin>>adjList[i].data; // 输入顶点信息 37 | G->adjList[i].firstedge = NULL; // 将边表置为空表 38 | } 39 | // 建立边表 40 | for(k = 0; k < G->numEdges; k++) { 41 | cin>>"please input edge's (vi,vj): "<>i>>j; 43 | e = (EdgeNode *)malloc(sizeof(EdgeNode)); // 生成边表结点 44 | e->adjvex = j; // 邻接序号为j 45 | e->next = G->adjList[i].firstedge; // 将e指针指向当前顶点指向的结点 46 | G->adjList[i].firstedge = e; // 将当前顶点的指针指向e 47 | e = (EdgeNode *)malloc(sizeof(EdgeNode)); // 生成边表结点 48 | e->adjvex = i; // 邻接序号为i 49 | e->next = G->adjList[j].firstedge; // 将e指针指向当前顶点指向的结点 50 | G->adjList[j].firstedge = e; // 将当前顶点的指针指向e 51 | } 52 | } -------------------------------------------------------------------------------- /string/kmp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | /*通过计算返回字串T的next数组*/ 7 | void get_next(String T, int *next) { 8 | int i,j; 9 | i = 1,j = 0; 10 | next[1] = 0; 11 | while(i < T[0]) { // T[0]表示串T的长度 12 | if (j == 0 || T[i] == T[j]) // T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 13 | { 14 | ++i; 15 | ++j; 16 | next[i] = j; 17 | } 18 | else { 19 | j = next[j] // 若字符不相同,则j值回溯 20 | } 21 | } 22 | } 23 | 24 | /*返回字串T在主串S中第pos个字符之后的位置,若不存在返回0*/ 25 | int Index_KMP(String S, String T, int pos) { 26 | int i = pos; // i用于主串S当前位置下标值,若pos不为1,则从pos位置开始匹配 27 | int j = 1; // j用于字串T中当前位置下标值 28 | int next[255]; 29 | get_next(T, next); // 对串T做分析,得到next数组 30 | while(i <= S[0] && j < T[0]) { // 若i小于S的长度且j小于T的长度时,循环继续 31 | if (j == 0 || S[i] == T[j]) // 两字母相等则继续 32 | { 33 | ++i; 34 | ++j; 35 | } 36 | else{ // 指针后退重新开始匹配 37 | j = next[i]; // j退回合适的位置,i值不变 38 | } 39 | } 40 | if (j > T[0]) 41 | { 42 | return i-T[0]; 43 | }else{ 44 | return 0; 45 | } 46 | } 47 | 48 | /*求模式串T的next函数修正值并存入数组nextal*/ 49 | void get_nextval(String T, int *nextval) { 50 | int i = 1, j = 0; 51 | nextval[1] = 0; 52 | while(i < T[0]) { 53 | if (j == 0 || T[i] == T[j]) // T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 54 | { 55 | ++i; 56 | ++j; 57 | if (T[i] != T[j]) // 若当前字符与前缀字符不同,则当前的j为nextval在i位置的值 58 | { 59 | nextval[i] = j; 60 | }else { // 若相同,则将前缀字符的nextval值赋值给nextval在i的位置的值 61 | nextval[i] = nextval[j]; 62 | } 63 | } 64 | else{ 65 | j = nextval[j]; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # data-structure-study 2 | 基于《大话数据结构》进行数据结构的学习 3 | ## 线性表 4 | - [单链表](https://github.com/Nate-yu/data-structure-study/blob/master/linear_list/link_list.cpp) 5 | - [栈的顺序存储结构](https://github.com/Nate-yu/data-structure-study/blob/master/linear_list/sq_stack.cpp) 6 | - [两栈共享空间](https://github.com/Nate-yu/data-structure-study/blob/master/linear_list/sq_double_stack.cpp) 7 | - [栈的链式存储结构](https://github.com/Nate-yu/data-structure-study/blob/master/linear_list/link_stack.cpp) 8 | - [循环队列的顺序存储](https://github.com/Nate-yu/data-structure-study/blob/master/linear_list/sq_queue.cpp) 9 | - [队列的链表结构](https://github.com/Nate-yu/data-structure-study/blob/master/linear_list/link_queue.cpp) 10 | ## 串 11 | - [查找字符子串位置](https://github.com/Nate-yu/data-structure-study/blob/master/string/compare_string.cpp) 12 | - [KMP字符串匹配](https://github.com/Nate-yu/data-structure-study/blob/master/string/kmp.cpp) 13 | ## 树 14 | - [树的各种存储结构](https://github.com/Nate-yu/data-structure-study/blob/master/tree/tree_struct.cpp) 15 | - [二叉树的创建与遍历](https://github.com/Nate-yu/data-structure-study/blob/master/tree/bi_tree.cpp) 16 | ## 图 17 | - [无向图的邻接矩阵存储结构](https://github.com/Nate-yu/data-structure-study/blob/master/graph/m_graph.cpp) 18 | - [无向图的邻接表存储结构](https://github.com/Nate-yu/data-structure-study/blob/master/graph/graph_adj_list.cpp) 19 | - [图的邻接矩阵深度优先遍历操作](https://github.com/Nate-yu/data-structure-study/blob/master/graph/dfs.cpp) 20 | - [图的邻接表深度优先遍历操作](https://github.com/Nate-yu/data-structure-study/blob/master/graph/dfs_adj_list.cpp) 21 | ## 查找 22 | - [二分查找](https://github.com/Nate-yu/data-structure-study/blob/master/search/binary_search.cpp) 23 | ## 排序 24 | - [冒泡排序](https://github.com/Nate-yu/data-structure-study/blob/master/sort/bubble_sort.cpp) -------------------------------------------------------------------------------- /linear_list/link_list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | typedef int ElementType; 8 | 9 | typedef struct Node 10 | { 11 | ElementType data; 12 | struct Node *next; 13 | }Node; 14 | typedef struct Node *LinkList; 15 | 16 | /*返回L中第i个元素的值*/ 17 | ElementType GetElem(LinkList *L, int i) { 18 | int j; 19 | ElementType e; 20 | LinkList p; 21 | p = (*L)->next; // 让p指向链表L的第一个结点 22 | j = 1; // 计数器 23 | while(p && j < i) { // 当p不为空且计数器j没有等于i时 24 | p = p->next; 25 | ++j; 26 | } 27 | if (!p || j > i) // 第i个结点不存在 28 | return 0; 29 | e = p->data; 30 | return e; 31 | } 32 | 33 | /*在L中第i个结点位置之前插入新的数据元素e,L的长度加1*/ 34 | bool ListInsert(LinkList *L, int i, ElementType e) { 35 | int j; 36 | LinkList p,s; 37 | p = *L; 38 | j = 1; 39 | while(p && j < i) { 40 | p = p->next; 41 | ++j; 42 | } 43 | if (!p || j > i) 44 | return false; 45 | s = (LinkList)malloc(sizeof(Node)); // 生成新结点 46 | s->data = e; 47 | 48 | /*开始插入新结点*/ 49 | s->next = p->next; // 将p的后继结点赋值给s的后继 50 | p->next = s; // 将s赋值给p的后继 51 | return true; 52 | } 53 | 54 | /*删除L的第i个结点,并用e返回其值,L的长度减1*/ 55 | bool ListDelete(LinkList *L, int i) { 56 | LinkList p,q; 57 | int j; 58 | p = *L; 59 | j = 1; 60 | while(p->next && j < i) { // 遍历寻找第i-1个结点 61 | p = p->next; 62 | ++j; 63 | } 64 | if (!(p->next) || j > i) 65 | return false; 66 | 67 | /*开始删除第i个结点*/ 68 | q = p->next; 69 | p->next = q->next; // 将q的后继结点赋值给p的后继 70 | free(q); 71 | return true; 72 | } 73 | 74 | /*随机产生n个元素的值,建立带表头结点的单链线性表L(头插法,栈)*/ 75 | void CreateListHead(LinkList *L,int n) { 76 | LinkList p; 77 | srand(time(0)); 78 | *L = (LinkList)malloc(sizeof(Node)); 79 | (*L)->next = NULL; // 建立一个带头结点的单链表 80 | for(int i = 0; i < n; i++) { 81 | p = (LinkList)malloc(sizeof(Node)); // 生成新结点 82 | p->data = rand()%100+1; // 随机生成100以内的数字 83 | p->next = (*L)->next; // 将L的后继结点(头结点)赋值给p(新结点)的后继 84 | (*L)->next = p; // 插入到表头 85 | } 86 | } 87 | 88 | /*随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法,队列)*/ 89 | void CreateListTail(LinkList *L, int n) { 90 | LinkList p,tail; 91 | srand(time(0)); 92 | *L = (LinkList)malloc(sizeof(Node)); 93 | tail = *L; // tail为指向尾部的结点 94 | for(int i = 0; i < n; i++) { 95 | p = (Node *) malloc(sizeof(Node)); 96 | p->data = rand() % 100 +1; 97 | tail->next = p; // 将表尾终端结点的指针指向新结点 98 | tail = p; // 将当前的新结点定义为表尾终端结点 99 | } 100 | tail->next = NULL; // 循环结束后,将当前结点的指针域置空,表示当前链表结束 101 | } 102 | 103 | /*单链表的整表删除*/ 104 | bool ClearList(LinkList *L) { 105 | LinkList p,q; 106 | p = (*L)->next; // p指向第一个结点 107 | while(p) { 108 | q = p->next; 109 | free(p); 110 | p = q; 111 | } 112 | (*L)->next = NULL; 113 | return true; 114 | } 115 | 116 | /*单链表的整表打印*/ 117 | void ListPrint(LinkList *L) { 118 | LinkList p = *L; 119 | int j = 1; 120 | while(p->next) { 121 | p = p->next; 122 | cout<data<<" "; 123 | ++j; 124 | } 125 | } 126 | 127 | int main() 128 | { 129 | LinkList *L; 130 | L = (LinkList*)malloc(sizeof(Node)); 131 | int n; 132 | cout<<"Please input the size of the linklist that you want to create: "; 133 | cin>>n; 134 | 135 | /*单链表的初始化(用尾插法建立单链表)*/ 136 | CreateListTail(L,n); 137 | cout<<"The linklist: "<>i; 145 | cout<<"The "<