一、线性表
1、线性表的顺序存储结构
(1)线性表顺序存储结构代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #define MAXSIZE 20 2 typedef int ElemType; 3 typedef struct 4 { 5 ElemType data[MAXSIZE]; 6 int length; // 线性表当前长度 7 } SqList;
(2)获得元素操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #define OK 1 2 #define ERROR 0 3 #define TRUE 1 4 #define FALSE 0 5 6 typedef int Status; 7 8 // Status 是函数的类型,其值是函数结果状态代码,如OK等。 9 // 初始条件:顺序线性表L已存在,1 <= i <= ListLength(L) 10 // 操作结果:用e返回L中第i个数据元素的值。 11 12 Status GetElem(SqList L, int i, ElemType *e) 13 { 14 if( L.length==0 || i<1 || i>L.length ) 15 { 16 return ERROR; 17 } 18 *e = L.data[i-1]; 19 20 return OK; 21 }
(3)插入操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 初始条件:顺序线性表L已存在,1<=i<=ListLength(L)。 */ 2 /* 操作结果:在L中第i个位置之前插入新的数据元素e,L长度+1。*/ 3 4 Status ListInsert(SqList *L, int i, ElemType e) 5 { 6 int k; 7 8 if( L->length == MAXSIZE ) // 顺序线性表已经满了 9 { 10 return ERROR; 11 } 12 if( i<1 || i>L->length+1) // 当i不在范围内时 13 { 14 return ERROR; 15 } 16 if( i <= L->length ) // 若插入数据位置不在表尾 17 { 18 /* 将要插入位置后数据元素向后移动一位 */ 19 for( k=L->length-1; k >= i-1; k-- ) 20 { 21 L->data[k+1] = L->data[k]; 22 } 23 } 24 25 L->data[i-1] = e; // 将新元素插入 26 L->length++; 27 28 return OK; 29 }
(4)删除操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 初始条件:顺序线性表L已存在,1<=i<=ListLength(L) */ 2 /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度-1 */ 3 Status ListDelete(SqList *L, int i, ElemType *e) 4 { 5 int k; 6 7 if( L->length == 0 ) 8 { 9 return ERROR; 10 } 11 if( i<1 || i>L->length ) 12 { 13 return ERROR; 14 } 15 16 *e = L->data[i-1]; 17 18 if( i < L->length ) 19 { 20 for( k=i; k < L->length; k++ ) 21 { 22 L->data[k-1] = L->data[k]; 23 } 24 } 25 26 L->length--; 27 28 return OK; 29 }
2、单链表
(1)、单链表存储结构
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 typedef struct Node 2 { 3 ElemType data; // 数据域 4 struct Node* Next; // 指针域 5 } Node; 6 typedef struct Node* LinkList;
(2)单链表的读取
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 初始条件:顺序线性表L已存在,1<=i<=ListLength(L) */ 2 /* 操作结果:用e返回L中第i个数据元素的值 */ 3 4 Status GetElem( LinkList L, int i, ElemType *e ) 5 { 6 int j; 7 LinkList p; 8 9 p = L->next; 10 j = 1; 11 12 while( p && j<i ) 13 { 14 p = p->next; 15 ++j; 16 } 17 18 if( !p || j>i ) 19 { 20 return ERROR; 21 } 22 23 *e = p->data; 24 25 return OK; 26 }
(3)单链表的插入
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 初始条件:顺序线性表L已存在,1<=i<=ListLength(L) */ 2 /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */ 3 4 Status ListInsert(LinkList *L, int i, ElemType e) 5 { 6 int j; 7 LinkList p, s; 8 9 p = *L; 10 j = 1; 11 12 while( p && j<i ) // 用于寻找第i个结点 13 { 14 p = p->next; 15 j++; 16 } 17 18 if( !p || j>i ) 19 { 20 return ERROR; 21 } 22 23 s = (LinkList)malloc(sizeof(Node)); 24 s->data = e; 25 26 s->next = p->next; 27 p->next = s; 28 29 return OK; 30 }
(4)单链表的删除
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 初始条件:顺序线性表L已存在,1<=i<=ListLength(L) */ 2 /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度-1 */ 3 4 Status ListDelete(LinkList *L, int i, ElemType *e) 5 { 6 int j; 7 LinkList p, q; 8 9 p = *L; 10 j = 1; 11 12 while( p->next && j<i ) 13 { 14 p = p->next; 15 ++j; 16 } 17 18 if( !(p->next) || j>i ) 19 { 20 return ERROR; 21 } 22 23 q = p->next; 24 p->next = q->next; 25 26 *e = q->data; 27 free(q); 28 29 return OK; 30 }
(5)单链表的整表创建
a.头插法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 头插法建立单链表示例 */ 2 3 void CreateListHead(LinkList *L, int n) 4 { 5 LinkList p; 6 int i; 7 8 srand(time(0)); // 初始化随机数种子 9 10 *L = (LinkList)malloc(sizeof(Node)); 11 (*L)->next = NULL; 12 13 for( i=0; i < n; i++ ) 14 { 15 p = (LinkList)malloc(sizeof(Node)); // 生成新结点 16 p->data = rand()%100+1; 17 p->next = (*L)->next; 18 (*L)->next = p; 19 } 20 }
b.尾插法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 尾插法建立单链表演示 */ 2 3 void CreateListTail(LinkList *L, int n) 4 { 5 LinkList p, r; 6 int i; 7 8 srand(time(0)); 9 *L = (LinkList)malloc(sizeof(Node)); 10 r = *L; 11 12 for( i=0; i < n; i++ ) 13 { 14 p = (Node *)malloc(sizeof(Node)); 15 p->data = rand()%100+1; 16 r->next = p; 17 r = p; // 备注:初学者可能很难理解这句,重点解释。 18 } 19 20 r->next = NULL; 21 }
(6)单链表的整表删除
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 Status ClearList(LinkList *L) 2 { 3 LinkList p, q; 4 5 p = (*L)->next; 6 7 while(p) 8 { 9 q = p->next; 10 free(p); 11 p = q; 12 } 13 14 (*L)->next = NULL; 15 16 return OK; 17 }
3、静态链表
(1)线性表的静态链表存储结构
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #define MAXSIZE 1000 2 typedef struct 3 { 4 ElemType data; // 数据 5 int cur; // 游标(Cursor) 6 } Component, StaticLinkList[MAXSIZE];
(2)静态链表进行初始化
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 Status InitList(StaticLinkList space) 2 { 3 int i; 4 for( i=0; i < MAXSIZE-1; i++ ) 5 space[i].cur = i + 1; 6 7 space[MAXSIZE-1].cur = 0; 8 9 return OK; 10 }
(3)获得空闲分量的下标
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 int Malloc_SLL(StaticLinkList space) 2 { 3 int i = space[0].cur; 4 if( space[0].cur ) 5 space[0].cur = space[i].cur; 6 // 把它的下一个分量用来作为备用。 7 return i; 8 }
(4)静态链表的插入
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 在静态链表L中第i个元素之前插入新的数据元素e */ 2 3 Status ListInsert( StaticLinkList L, int i, ElemType e ) 4 { 5 int j, k, l; 6 7 k = MAX_SIZE - 1; // 数组的最后一个元素 8 if( i<1 || i>ListLength(L)+1 ) 9 { 10 return ERROR; 11 } 12 13 j = Malloc_SLL(L); 14 if( j ) 15 { 16 L[j].data = e; 17 for( l=1; l <= i-1; l++ ) 18 { 19 k = L[k].cur; 20 } 21 L[j].cur = L[k].cur; 22 L[k].cur = j; 23 24 return OK; 25 } 26 27 return ERROR; 28 }
(5)静态链表的删除操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 删除在L中的第i个数据元素 */ 2 Status ListDelete(StaticLinkList L, int i) 3 { 4 int j, k; 5 6 if( i<1 || i>ListLength(L) ) 7 { 8 return ERROR; 9 } 10 11 k = MAX_SIZE - 1; 12 13 for( j=1; j <= i-1; j++ ) 14 { 15 k = L[k].cur; // k1 = 1, k2 = 5 16 } 17 18 j = L[k].cur; // j = 2 19 L[k].cur = L[j].cur; 20 21 Free_SLL(L, j); 22 23 return OK; 24 } 25 26 /* 将下标为k的空闲结点回收到备用链表 */ 27 void Free_SLL(StaticLinkList space, int k) 28 { 29 space[k].cur = space[0].cur; 30 space[0].cur = k; 31 } 32 33 /* 返回L中数据元素个数 */ 34 int ListLength(StaticLinkList L) 35 { 36 int j = 0; 37 int i = L[MAXSIZE-1].cur; 38 39 while(i) 40 { 41 i = L[i].cur; 42 j++; 43 } 44 45 return j; 46 }
4、循环链表
(1)初始化部分
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /*初始化循环链表*/ 2 void ds_init(node **pNode) 3 { 4 int item; 5 node *temp; 6 node *target; 7 8 printf("输入结点的值,输入0完成初始化\n"); 9 10 while(1) 11 { 12 scanf("%d", &item); 13 fflush(stdin); 14 15 if(item == 0) 16 return; 17 18 if((*pNode) == NULL) 19 { /*循环链表中只有一个结点*/ 20 *pNode = (node*)malloc(sizeof(struct CLinkList)); 21 22 if(!(*pNode)) 23 exit(0); 24 25 (*pNode)->data = item; 26 (*pNode)->next = *pNode; 27 } 28 else 29 { 30 /*找到next指向第一个结点的结点*/ 31 for(target = (*pNode); target->next != (*pNode); target = target->next) 32 ; 33 34 /*生成一个新的结点*/ 35 temp = (node *)malloc(sizeof(struct CLinkList)); 36 37 if(!temp) 38 exit(0); 39 40 temp->data = item; 41 temp->next = *pNode; 42 target->next = temp; 43 } 44 } 45 }
(2)插入部分
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /*链表存储结构的定义*/ 2 typedef struct CLinkList 3 { 4 int data; 5 struct CLinkList *next; 6 }node; 7 8 /*插入结点*/ 9 /*参数:链表的第一个结点,插入的位置*/ 10 void ds_insert(node **pNode , int i) 11 { 12 node *temp; 13 node *target; 14 node *p; 15 int item; 16 int j = 1; 17 18 printf("输入要插入结点的值:"); 19 scanf("%d", &item); 20 21 if(i == 1) 22 { //新插入的结点作为第一个结点 23 temp = (node *)malloc(sizeof(struct CLinkList)); 24 25 if(!temp) 26 exit(0); 27 28 temp->data = item; 29 30 /*寻找到最后一个结点*/ 31 for(target = (*pNode); target->next != (*pNode); target = target->next) 32 ; 33 34 temp->next = (*pNode); 35 target->next = temp; 36 *pNode = temp; 37 } 38 else 39 { 40 target = *pNode; 41 42 for( ; j < (i-1); ++j ) 43 { 44 target = target->next; 45 } 46 47 // target指向第三个元素的 48 49 temp = (node *)malloc(sizeof(struct CLinkList)); 50 51 if(!temp) 52 exit(0); 53 54 temp->data = item; 55 56 p = target->next; 57 target->next = temp; 58 temp->next = p; 59 } 60 }
(3)删除部分
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /*删除结点*/ 2 void ds_delete(node **pNode, int i) 3 { 4 node *target; 5 node *temp; 6 int j = 1; 7 8 if(i == 1) 9 { //删除的是第一个结点 10 /*找到最后一个结点*/ 11 for(target = *pNode; target->next != *pNode;target = target->next) 12 ; 13 14 temp = *pNode; 15 *pNode = (*pNode)->next; 16 target->next = *pNode; 17 free(temp); 18 } 19 else 20 { 21 target = *pNode; 22 23 for( ; j < i-1; ++j) 24 { 25 target = target->next; 26 } 27 28 temp = target->next; 29 target->next = temp->next; 30 free(temp); 31 } 32 }
(4)返回结点所在位置
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /*返回结点所在位置*/ 2 int ds_search(node *pNode, int elem) 3 { 4 node *target; 5 int i = 1; 6 7 for(target = pNode; target->data != elem && target->next != pNode; ++i) 8 { 9 target = target->next; 10 } 11 12 if(target->next == pNode) /*表中不存在该元素*/ 13 return 0; 14 else 15 return i; 16 }
5、双向链表
(1)双向链表结点结构
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 typedef struct DualNode 2 { 3 ElemType data; 4 struct DualNode *prior; //前驱结点 5 struct DualNode *next; //后继结点 6 } DualNode, *DuLinkList;
(2)双向链表的插入操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 s->next = p; 2 s->prior = p->prior; 3 p->prior->next = s; 4 p->prior = s;
(3)双向链表的删除操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 p->prior->next = p->next; 2 p->next->prior = p->prior; 3 free(p);
二、栈
1、栈
(1)栈的顺序存储结构
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 typedef struct 2 { 3 ElemType *base; 4 ElemType *top; 5 int stackSize; 6 }sqStack;
(2)创建一个栈
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #define STACK_INIT_SIZE 100 2 initStack(sqStack *s) 3 { 4 s->base = (ElemType *)malloc( STACK_INIT_SIZE * sizeof(ElemType) ); 5 if( !s->base ) 6 exit(0); 7 s->top = s->base; // 最开始,栈顶就是栈底 8 s->stackSize = STACK_INIT_SIZE; 9 }
(3)入栈操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #define SATCKINCREMENT 10 2 3 Push(sqStack *s, ElemType e) 4 { 5 // 如果栈满,追加空间 6 if( s->top – s->base >= s->stackSize ) 7 { 8 s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType)); 9 if( !s->base ) 10 exit(0); 11 12 s->top = s->base + s->stackSize; // 设置栈顶 13 s->stackSize = s->stackSize + STACKINCREMENT; // 设置栈的最大容量 14 } 15 16 *(s->top) = e; 17 s->top++; 18 }
(4)出栈操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 Pop(sqStack *s, ElemType *e) 2 { 3 if( s->top == s->base ) // 栈已空空是也 4 return; 5 *e = *--(s->top); 6 }
(5)销毁一个栈
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 DestroyStack(sqStack *s){ 2 int i, len; 3 len = s->stackSize; 4 for( i=0; i < len; i++ ){ 5 free( s->base ); 6 s->base++; 7 } 8 s->base = s->top = NULL; 9 s->stackSize = 0; 10 }
(6)计算栈的当前容量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 int StackLen(sqStack s) 2 { 3 return(s.top – s.base); // 初学者需要重点讲解 4 }
2、栈的链式存储结构
(1)栈的链式存储结构
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 teypedef struct StackNode 2 { 3 ElemType data; // 存放栈的数据 4 struct StackNode *next; 5 } StackNode, *LinkStackPtr; 6 teypedef struct LinkStack 7 { 8 LinkStackPrt top; // top指针 9 int count; // 栈元素计数器 10 }
(2)进栈操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 Status Push(LinkStack *s, ElemType e) 2 { 3 LinkStackPtr p = (LinkStackPtr) malloc (sizeof(StackNode)); 4 p->data = e; 5 p->next = s->top; 6 s->top = p; 7 s->count++; 8 return OK; 9 }
(3)出栈操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 Status Pop(LinkStack *s, ElemType *e) 2 { 3 LinkStackPtr p; 4 if( StackEmpty(*s) ) // 判断是否为空栈 5 return ERROR; 6 *e = s->top->data; 7 p = s->top; 8 s->top = s->top->next; 9 free(p); 10 s->count--; 11 return OK; 12 }
三、队列
1、队列
(1)创建一个队列
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 initQueue(LinkQueue *q) 2 { 3 q->front=q->rear=(QueuePtr)malloc(sizeof(QNode)); 4 if( !q->front ) 5 exit(0); 6 q->front->next = NULL; 7 }
(2)入队列操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 InsertQueue(LinkQueue *q, ElemType e) 2 { 3 QueuePtr p; 4 p = (QueuePtr)malloc(sizeof(QNode)); 5 if( p == NULL ) 6 exit(0); 7 p->data = e; 8 p->next = NULL; 9 q->rear->next = p; 10 q->rear = p; 11 }
(3)出队列操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 DeleteQueue(LinkQueue *q, ELemType *e) 2 { 3 QueuePtr p; 4 if( q->front == q->rear ) 5 return; 6 p = q->front->next; 7 *e = p->data; 8 q->front->next = p->next; 9 if( q->rear == p ) 10 q->rear = q->front; 11 free(p); 12 }
(4)销毁一个队列
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 DestroyQueue(LinkQueue *q) 2 { 3 while( q->front ) { 4 q->rear = q->front->next; 5 free( q->front ); 6 q->front = q->rear; 7 } 8 }
2、循环队列
(1)定义一个循环队列
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #define MAXSIZE 100 2 typedef struct 3 { 4 ElemType *base; // 用于存放内存分配基地址 5 // 这里你也可以用数组存放 6 int front; 7 int rear; 8 }
(2)初始化一个循环队列
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 initQueue(cycleQueue *q) 2 { 3 q->base = (ElemType *) malloc (MAXSIZE * sizeof(ElemType)); 4 if( !q->base ) 5 exit(0); 6 q->front = q->rear = 0; 7 }
(3)入队列操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 InsertQueue(cycleQueue *q, ElemType e) 2 { 3 if( (q->rear+1)%MAXSIZE == q->front ) 4 return; // 队列已满 5 q->base[q->rear] = e; 6 q->rear = (q->rear+1) % MAXSIZE; 7 }
(4)出队列操作
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 DeleteQueue(cycleQueue *q, ElemType *e) 2 { 3 if( q->front == q->rear ) 4 return ; // 队列为空 5 *e = q->base[q->front]; 6 q->front = (q->front+1) % MAXSIZE; 7 }
四、递归
1、斐波那契数列的递归实现
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 0,当n=0 3 F(n) = 1,当n=1 4 F(n-1)+F(n-2),当n>1 5 */ 6 int Fib(int i) 7 { 8 if( i < 2 ) 9 return i == 0 ? 0 : 1; 10 return Fib(i-1) + Fib(i-2); 11 }
2、计算n的阶乘n!
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 1 n = 0 3 n! = 4 n*(n-1) n > 0 5 */ 6 7 int factorial( n ) 8 { 9 if( 0 == n ) return 1; 10 else return n * factorial( n - 1 ); 11 }
3、实现将输入的任意长度的字符串反向输出的功能。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 将“#”作为一个输入结束的条件。 3 */ 4 void print() 5 { 6 char a; 7 scanf(“%c”, &a); 8 if( a !=‘#’) print(); 9 if( a !=‘#’) printf(“%c”, a); 10 }
五、字符串
(1)BF算法
有两个字符串S和T,长度为N和M。首先S[1]和T[1]比较,若相等,则再比较S[2]和T[2],一直到T[M]为止;若S[1]和T[1]不等,则T向右移动一个字符的位置,再依次进行比较。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 // 返回子串T在主串S中第pos个字符之后的位置 2 // 若不存在,则返回0 3 // T非空,1 <= pos <= strlen(S) 4 // 注意:我们这里为了表述方便,字符串使用了第一个元素表示长度的方式。 5 6 int index( String S, String T, int pos ) 7 { 8 int i = pos; // i用于主串S中当前位置下标 9 int j = 1; // j用于子串T中当前位置下标 10 11 while( i <= S[0] && j <= T[0] ) // i或j其中一个到达尾部即终止搜索! 12 { 13 if( S[i] == T[i] ) // 若相等则继续下一个元素匹配 14 { 15 i++; 16 j++; 17 } 18 else // 若失配则j回溯到第一个元素从新匹配 19 { 20 i = i-j+2; // i回溯到上次匹配首位的下一个元素,这是效率低下的关键! 21 j = 1; 22 } 23 } 24 25 if( j > T[0] ) 26 { 27 return i - T[0]; 28 } 29 else 30 { 31 return 0; 32 } 33 }
六、数
1、双亲表示法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 // 树的双亲表示法结点结构定义 2 #define MAX_TREE_SIZE 100 3 4 typedef int ElemType; 5 6 typedef struct PTNode 7 { 8 ElemType data; // 结点数据 9 int parent; // 双亲位置 10 }PTNode; 11 12 typedef struct 13 { 14 PTNode nodes[MAX_TREE_SIZE]; 15 int r; // 根的位置 16 int n; // 结点数目 17 }PTree;
2、孩子表示法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #define MAX_TREE_SIZE 100 2 3 typedef char ElemType; 4 5 // 孩子结点 6 typedef struct CTNode 7 { 8 int child; // 孩子结点的下标 9 struct CTNode *next; // 指向下一个孩子结点的指针 10 } *ChildPtr; 11 12 // 表头结构 13 typedef struct 14 { 15 ElemType data; // 存放在树中的结点的数据 16 int parent; // 存放双亲的下标 17 ChildPtr firstchild; // 指向第一个孩子的指针 18 } CTBox; 19 20 // 树结构 21 typedef struct 22 { 23 CTBox nodes[MAX_TREE_SIZE]; // 结点数组 24 int r, n; 25 }
3、孩纸兄弟表示法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 孩纸兄弟表示法 3 */ 4 typedef struct CSNode 5 { 6 TElemType data; 7 struct CSNode *firstchild,*rightsib;//第一个孩纸,和它右边的孩纸 8 }CSNode,*CSTree;
4、二叉树的儿茶链表结点结构定义
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 二叉树的二叉链表结点结构定义 3 */ 4 5 typedef struct BiTNode 6 { 7 TElemType data;//结点数据 8 struct BiTNode *lchild,*rchild;//左右孩纸 9 }BiTNode,*BiTree;
5、二叉树前序遍历法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 二叉树前序遍历法 3 */ 4 void PreOrderTraverse(BiTree T) 5 { 6 if(T==ULL) 7 return; 8 9 printf("%c",T->data);//显示结点数据,可以更改为其他队结点操作 10 11 PreOrderTraverse(T->lchild);//再先序遍历左子树 12 13 PreOrderTraverse(T->rchild);//最后先序右子树 14 15 }
6、二叉中序遍历算法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 二叉树中序遍历算法 3 */ 4 5 void InOrderTraverse(BiTree T) 6 { 7 if(T==NULL) 8 return; 9 10 InOrderTraverse(T->lchild);//中序遍历左子树 11 12 printf("%c",T->data);//显示节点数据,可以更改为其他对结点操作 13 14 InOrderTraverse(T->rchild);//最后中序遍历右子树 15 }
7、二叉后序遍历算法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 二叉后序遍历递归算法 3 */ 4 5 void PostOrderTraverse(BiTree T) 6 { 7 if(T==NULL) 8 return; 9 10 PostOrderTraverse(T->lchild)//先后序遍历左子树 11 12 PostOrderTraverse(T->rchild);//再后序遍历右子树 13 14 printf("%c",T->data);//显示结点数据,可以更改为其他对结点操作 15 16 }
8、二叉树的建立
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 二叉树的建立,按前序输入二叉树中结点的值,#表示空树链表表示二叉数T 3 */ 4 void CreateBiTree(BiTree *T) 5 { 6 TElemType ch; 7 scanf("%c",&ch);//输入字符串 8 9 if(ch=='#')//如果是空树 10 *T=NULL; 11 12 else 13 { 14 *T=(BiTree)malloc(sizeof(BiTNode));//获取空间 15 16 if(!*T) 17 exit(OVERFLOW); 18 19 (*T)->data=ch;//生成根结点 20 CreateBiTree(&(*T>lhild);//构造左子树 21 CreateBiTree(&(*T>rhild);//构造右子树 22 } 23 24 }
9、线索二叉树结构定义
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 线索二叉树结构定义 3 */ 4 5 typedef enum 6 { 7 Link,//Link==0表示指向左右孩纸指针 8 Thread//Thread==1表示指向前驱或后继的线索 9 }PointerTag; 10 11 typedef struct BitThrNode 12 { 13 TElemType data;//结点标志 14 struct BiThrNode *lchilde,*rchild;//左右孩纸指针 15 PointerTag LTag; 16 PointerTag RTag;//左右标志 17 }BitThrNode,*BitThrTree;
10、中序遍历线索化的递归函数
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 中序遍历线索化的递归函数 3 */ 4 void InThreading(BiThrTree p) 5 { 6 if(p) 7 { 8 InTreading(p->lchild);//递归左子树线索花 9 10 if(!p->lchild)//没有左孩纸 11 { 12 p->LTag=Thread;//前驱线索 13 p->child=pre;//左孩纸指针指向前驱 14 } 15 16 if(!pre->rchild)//没有右孩纸 17 { 18 pre->RTag=Thread;//后继线索 19 pre->rchild=p;//前驱右孩纸指针指向后继 20 } 21 22 pre=p;//保持pre指向p的前驱 23 24 InThreading(p->rchild);//递归右子树线索化 25 26 } 27 }
11、遍历
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* 2 T指向头结点,头结点左链lchild指向根结点,头结点右链rchild指向中序遍历的,最后一个结点。 3 中序遍历二叉线索链表表示的二叉树T 4 */ 5 6 7 Status InOrderTraverse_Thr(BiThrTree T) 8 { 9 BiThrTree p; 10 p=T->child;//p指向根结点 11 12 while(p!=T)//空树或遍历结束时,p==T 13 { 14 while(p->LTag==Link)//当LTag==0时循环到中序序列第一个节点 15 p=p->lchild; 16 17 printf("%c",p->data);//显示结点数据,可以更改为其他对结点操作 18 19 while(p->RTag==Thread && p->rchild!=T) 20 { 21 p=p->rchild; 22 printf("%c",p->data); 23 } 24 25 p=p->child;//p进至其右子树根 26 } 27 28 return OK; 29 }