2018
来源:互联网 发布:魅族官方网络授权店 编辑:程序博客网 时间:2024/03/29 23:15
请注意函数名为此题的大致意思,函数名后的数字为该章节编程题的序号,请注意以序号为准
——页面长请使用左侧目录
第2章
2.2
#include<stdio.h> #include<stdlib.h>#include<string.h>#define MAX 100typedef int type;typedef struct{ int len; type data[MAX];}sqList;bool mindel1(sqList *a,type *value){ if(a->len<=0) { printf("线性表为空!"); return -1; } int j=0; for(int i=1;i<a->len;i++) { if((a->data)[i]<a->data[j]) j=i; } *value=a->data[j]; a->data[j]=(a->data)[(a->len)-1]; return 0;}int nizhi2(sqList *a){ if(a->len<0) return -1; for(int i=0;i<=a->len/2;i++) { a->data[i]+=a->data[a->len-1-i] ; a->data[a->len-1-i]=a->data[i]-a->data[a->len-1-i]; a->data[i]-=a->data[a->len-1-i]; } return 0;}int delsameele3(sqList *a,type x) { //每遍历一个元素时都考虑其向前移动的位数 int k=0; for(int i=0;i<a->len;i++) if(a->data[i]!=x) a->data[i-k]=a->data[i]; else k++; a->len-=k;//否则最后的k个元素将重复出现,也符合定义 return 0;// 方法二:// for(int i=0;i<a->len;i++)// if(a->data[i]!=x)// a->data[k++]->data[i];//删除后的顺序表k上的元素总等于按顺序不等于x的i位置的元素// a->len=k; }int delsure4(sqList *a,type min,type max){ int k; if(min>=max||a->len<=0) return -1; for(int i=0;i<a->len;i++) if(a->data[i]>min&&a->data[i]<max) a->data[k++]=a->data[i];//删除后的顺序表k上的元素总等于按顺序不等于x的i位置的元素 a->len=k; return 0;}int delsure5(sqList *a,type min,type max){ int k; if(min>=max||a->len<=0) return -1; for(int i=0;i<a->len;i++) if(a->data[i]>=min&&a->data[i]<=max) a->data[k++]=a->data[i];//删除后的顺序表k上的元素总等于按顺序不等于x的i位置的元素 a->len=k; return 0;}int delsame6(sqList *a){ int k=0; for(int i=1;i<a->len;i++) if(a->data[i]>a->data[i-1])//若要实现逆序的顺序表去重则换位小于号 a->data[i-k]=a->data[i]; else if(a->data[i-1]=a->data[i]) k++; else return -1;//如果顺序表不是顺序则输出错误 a->len-=k; return 0; }bool isposorder(sqList *a)//非题{ for(int i=1;i<a->len;i++) if(a->data[i]<a->data[i-1]) return false; return true;}int combine7(sqList *a,sqList *b,sqList *c){ int i=0;int j=0;int k=0; c->len=a->len+b->len; if(!isposorder(a)||!isposorder(b)) return -1; else { while(j<a->len&&k<b->len) { if(a->data[j]<=b->data[k]) c->data[i++]=a->data[j++]; else c->data[i++]=b->data[k++]; } if(j==a->len) while(k<b->len) c->data[i++]=b->data[k++]; else while(j<a->len) c->data[i++]=a->data[j++]; return 0;} } if(a->data[i]>=a->len||a->data[i]<0) return -2; else t[a->data[i]]++; } for(int i=0;i<a->len;i++) if(t[i]>a->len/2) return i; return -1;}int change_8(sqList *a,int n) { reverse(a,0,a->len-1); reverse(a,0,a->len-1-n); reverse(a,a->len-n,a->len-1); return 0; } int insert9(sqList *a,int x) { int low=0;int high=a->len-1; int mid; if(!isposorder(a)) return -1; while(low<=high) { mid=(low+high)/2; if(x>=a->data[mid]) low=mid; else high=mid-1; } if(a->data[mid]==x&&high!=a->len-1) { a->data[mid]+=a->data[mid+1]; a->data[mid+1]=a->data[mid]-a->data[mid+1]; a->data[mid]=a->data[mid]-a->data[mid+1]; } if(low>high) { for(int i=a->len-1;i<high;i--) a->data[i+1]=a->data[i]; a->data[high+1]=x; a->len++; } return 0;}void reverse10(sqList *a,int m,int n)//把数组中的元素从下标为n到 下标为n的元素逆置 { for(int i=0;i<=(n-m)/2;i++) { int t; t=a->data[m+i]; a->data[m+i]=a->data[n-i]; a->data[n-i]=t; }} int leftmove10(sqList *a,int p){ //在第8题的基础上实际为数组交换位置,只不过此时不能用二分法时间复杂度为O(n) ,空间复杂度为O(1) reverse10(a,0,a->len-1); reverse10(a,0,a->len-p); reverse10(a,a->len-p+1,a->len-1); return 0;}int midpos11(sqList *a,sqList *b){ if(a->len!=b->len||!isposorder(a)||!isposorder(b)) return -1; //将两个升序数组合并成一个新的数组只用找到新数组第(n+n)/2上位置上元素时间复杂度为O(n) ,空间复杂度为O(1) int i,j,k;i=j=k=0; for(int m=1;m<=a->len;m++) if(a->data[i]<=b->data[j]) { if(i++==a->len||m==a->len) return a->data[--i]; } else { if(j++==b->len||m==a->len) return a->data[--j]; }}int mainele12(sqList *a) { //需要一个与原数组长度一致的空间,其i号记录原数组中值为i的元素个数 type t[a->len]; for(int i=0;i<a->len;i++) t[i]=0; for(int i=0;i<a->len;i++) { if(a->data[i]>=a->len||a->data[i]<0) return -2; else t[a->data[i]]++; } for(int i=0;i<a->len;i++) if(t[i]>a->len/2) return i; return -1;}
2.2测试用例
int main(void){ type value; int a[10]; sqList *sql=(sqList *)malloc(sizeof(sqList)); sqList *sql1=(sqList *)malloc(sizeof(sqList)); sqList *sql2=(sqList *)malloc(sizeof(sqList)); sql1->len=sql->len=10; sql2->len=sql->len+sql1->len;// for(int i=0;i<sql->len;i++)// scanf("%d",&sql1->data[i]);//顺序表赋值 for(int i=0;i<sql->len;i++) scanf("%d",&sql->data[i]);//此处应该注意scanf()函数里若加入空格等空白符会使输入多一次,原因复杂 // mindel(sql,&value);// printf("最小值为 %d\n",value);// for(int i=0;i<10;i++)// printf(" %d ",sql->data[i]);// nizhi(sql); // printf("":%d\n");// delsameele(sql,5);// delsame6(sql);// combine7(sql,sql1,sql2) ;// change_8(sql,4);// insert9(sql,1);// leftmove10(sql,3);// for(int i=0;i<sql->len;i++)// printf("%d ",sql->data[i]);// printf("%d",midpos11(sql,sql1)); printf("%d",mainele12(sql)); return 0;}
2.3
// 王道考研.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<stdio.h> #include<malloc.h> #include<stdlib.h>typedef int type;typedef struct lnode //定义链表结点的数据结构 { int data; struct lnode *next;}Lnode;typedef Lnode node;typedef struct dnode//定义双链表结点的数据结构 { int data; struct dnode *lnext; struct dnode *rnext;}Dnode;node *headinsert()//头插法创建链表 { int x; node *h = (node *)malloc(sizeof(node)); h->next = NULL; scanf_s("%d", &x); while (x != -1) { node *s = (node *)malloc(sizeof(node)); s->data = x; s->next = h->next; h->next = s; scanf_s("%d", &x); } return h;}node *tailinsert()//尾插法创建链表 { int x; node *h, *t; t = h = (node *)malloc(sizeof(node)); h->next = NULL; scanf_s("%d", &x); while (x != -1) { node *s = (node *)malloc(sizeof(node)); s->data = x; s->next = NULL; t->next = s; t = s; scanf_s("%d", &x); } return h;}node *insert(node *h, int n, int m, int b){ node *p; if (h == NULL) return h; p = h->next; if (b == 0) { if (p->data == n) { node *tem = (node *)malloc(sizeof(node)); tem->data = m; tem->next = p; h->next = tem; } while (p->next != NULL) { if ((p->next->data) == n) { node *tem = (node *)malloc(sizeof(node)); tem->data = m; tem->next = p->next; p->next = tem; p = p->next; } p = p->next; } } else { if ((h->next->data == n)) { node *tem = (node *)malloc(sizeof(node)); tem->data = m; tem->next = h->next->next; h->next->next = tem; p = p->next; } while (p != NULL) { if (p->data == n) { node *tem = (node *)malloc(sizeof(node)); tem->data = m; tem->next = p->next; p->next = tem; } p = p->next; } } return h;}int select(node *h, int n)//查找指定元素在链表中的第一次出现的位置 { int i = 1; while (h->data != n) { if (h->next == NULL) return 0; h = h->next; i++; } return i - 1;}int getlength(node *h){ node *p = h; int i = 0; while (p->next != NULL) { p = p->next; i++; } return i;}node *get(node *h, int n)//获取链表指定位置的结点指针 { node *p = h; int i; if (n>getlength(h) || n <= 0) return h; for (i = 1; i <= n; i++) p = p->next; return p;}void print(node *h)//打印链表的所有节点 { node *p = h->next; if (h == NULL) return; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); getchar();}void difference(node *a, node *b)//两个链表构成的集合求差运算,即a-b { node *q = b; node *p; node *pre, *r; pre = a; p = a->next; if (!p) return; while (p) { //printf("进入3"); q = b->next; while (q != NULL&&p->data != q->data) { // printf("进入1"); q = q->next; } if (q != NULL) { // printf("进入2"); r = p; pre->next = p->next; p = p->next; free(r); } else { pre = p; p = p->next; } }}void bubblesort1(node *h)//冒泡排序交换结点{ int w, i, change, j; node *p1, *p2, *p3; for (i = getlength(h), change = 1; i>1 && change; i--) { change = 0; for (j = 1; j<i; ++j) if (get(h, j)->data>get(h, j + 1)->data) { p1 = get(h, j - 1); p2 = get(h, j); p3 = get(h, j + 1); p2->next = p3->next; p3->next = p2; p1->next = p3; change = 1; } }}node *linkcombine(node *a, node *b){ node *p = a; node *q = b->next; node *prep = a; node *preq = b; node *tem; if (p == NULL) return b; if (q == NULL) return b; while (q != NULL) { printf("当前a:\n"); print(a); // printf("%d 1当前p的data\n",p->data); while (p->next != NULL&&p->next->data <= q->data) { p = p->next; //printf("%d 2当前p的data\n",p->data); } // printf("chuchuchu"); tem = q; //printf("%d 2插入的q值",tem->data); q = q->next; tem->next = p->next; p->next = tem; p = p->next; }}void recursiondel1(node *h, type x){ node *p; if (h == NULL) return; if (h->data == x) { p = h; h = h->next; free(p); recursiondel1(h, x); } else recursiondel1(h->next, x);}node *del2(node *h, int n)//删除指定元素的结点 { node *p = h; node *q; while (p->next != NULL) if ((p->next)->data == n) { q = p->next; p->next = q->next; free(q); // printf("删除3"); } else p = p->next; return h;}void r_print3(node *h){ if (h == NULL) return; r_print3(h->next); printf("%d ", h->data);}void delminest4(node *h){ node *p, *q, *min; if (h->next == NULL) return; p = h; min = q = h->next; while (q->next != NULL) { if (q->next->data<min->data) { p = q; min = q->next; } q = q->next; } p->next = min->next; free(min);}void reverse5(node *h)//将原链表就地倒置 { node *p = h->next; node *q; h->next = NULL; while (p != NULL) { q = p; p = p->next; q->next = h->next; h->next = q; }}void bubblesort6(node *h)//冒泡排序交换结点值{ int w, i, change, j; node *tem; for (i = getlength(h), change = 1; i>1 && change; i--) { change = 0; for (j = 1; j<i; ++j) if (get(h, j)->data>get(h, j + 1)->data) { w = get(h, j)->data; get(h, j)->data = get(h, j + 1)->data; get(h, j + 1)->data = w; change = 1; } }}int delvalue7(node *h, type a, type b){ node *h1 = h; while (h1->next != NULL) if (h1->next->data>a&&h1->next->data<b) { node *p = h1->next; h1->next = h1->next->next; free(p); } else h1 = h1->next; return 0;}node *searchsamenode8(node *h1, node *h2){ int m, n; m = n = 0; node *p1, *p2; p1 = h1->next; p2 = h2->next; while (p1->next != NULL) m++; while (p2->next != NULL) n++; if (m == 0 || n == 0) return NULL; if (m >= n) { m -= n; p1 = h1->next; while (m-->0) p1 = p1->next; } else { n -= m; p2 = h2->next; while (n-->0) p1 = p1->next; } if (p1 == p2) return p1; else if (p1 == p2 == NULL) return NULL; else { p1 = p1->next; p2 = p2->next; }}int posprint9(node *h){ //先将链表就地使用插入的方法排好序再一次输出并释放空间 node *p = h->next; node *q = p; while (q->next)//插入法排好正序 if (q->next->data >= q->data) q = q->next; else { if (q->next->data <= p->data) { h->next = q->next; q->next = q->next->next; h->next->next = p; // print(h); } else { while (!(p->data <= q->next->data&&p->next->data >= q->next->data)) p = p->next; node *tem = p->next; p->next = q->next; q->next = q->next->next; p->next->next = tem; // print(h); } p = h->next; } //打印节点值并释放结点所占有的空间 p = h; q = h->next; while (q) { printf("%d ", q->data); p = q; q = q->next; free(p); } free(h); //分析以上程序可知其时间复杂度花在遍历整个链表以及找到应插入位置的两个循环上,最差为o(n^2) 空间复杂度o(1); //方法二:每次找到当前链表的最小值后则进行删除,重复以上操作直至链表中一个元素也不剩 // node *p,*q,*tem; // while(h->next){ // p=h;q=p->next; // while(q->next) // { // if(q->next->data<p->next->data) // p=q; // else // q=q->next; // } // printf("%d ",p->next->data); // tem=p->next; // p->next=p->next->next; // free(tem) //} // free(h); return 0;}void resolve10(node *h, node *bh){ node *p = h->next; node *hh=NULL; hh->next = h; bh->next = p; while (p&&p->next) { h->next = p->next; p->next = h->next->next; p = p->next; h = h->next; } if (h->next != NULL) h->next = NULL; h = hh;}void pur_linklist12(node *h)//删除链表中的所有重复元素 { node *p = h->next; if (!p || !(p->next)) return; while (p != NULL) { node *q = p; node *tem; while (q->next != NULL) { if (q->next->data == p->data) { tem = q->next; q->next = q->next->next; free(tem); } else q = q->next; } p = p->next; }}bool isposorder(node *h){ node *p = h->next; while (p->next) if (p->next->data<p->data) return false; else p = p->next; return true;}node *combineneg13(node *h1, node *h2)//将升序的h1,h2利用原来已经有的空间把它们头插法合并到h1保证逆序{ //首先判断两个链表是不是正序的否则报错。再从头比较两个链表元素的大小然后使用头插法创建链表,而结点使用以前的结点 if (isposorder(h1) && isposorder(h2)) { node *h, *p, *q, *t; h=t = NULL; p = h1->next; q = h2->next; while (p||q) { if (!q||(p&&p->data <= q->data ))//此处注意因为短路逻辑两个或条件的先后顺序不能改变 { node *tem = p; //printf("%d\n", tem->data); p = p->next; tem->next = t; h->next = tem; t = tem; } if ((!p&&q)||(q&&p->data>q->data))//此处注意第一个或条件需要加上&&q,因为可能在上一个if中将p挪向空导致p,q同时为空,while还未来得及判断就要进入,会抛出异常 { node *tem = q; //printf("%d\n", tem->data); q = q->next; tem->next = t; h->next = tem; t = tem; } } return h; } else return NULL;}int comele15(node *h1, node *h2){ //从h1第一个元素开始进行删除,删除再h2中不存在的元素,直到遍历到h1的末尾, //为了充分利用有序的条件,应使h1,h2遍历一遍即可 if (!(isposorder(h1) && isposorder(h2))) return -1; node *p = h1; node *q = h2->next; while (q&&p->next) { node *tem; if (p->next->data < q->data) { tem = p; while (p->next&&p&&p->next->data < q->data) p = p->next; if (!p->next)//此处防止p只剩一个元素而要去访问p->nex->next的错误情况而直接退出 { tem->next = p->next; break; } if (p->next->data == q->data) tem->next = p->next; else { tem->next = p->next->next; p = p->next; } } else if (p->next->data == q->data) { p = p->next; q = q->next; tem = p; } else while (p->next&&q&&p->next->data > q->data) q = q->next; } p->next = NULL; return 0;}bool issonsequen16(node *h1, node *h2){ node *p = h1->next; node *q = h2->next; if (getlength(h1) < getlength(h2)) return false; while (p&&q) { if (p->data != q->data) p = p->next; node *m = p; while (q&&m) if (m->data != q->data || !m) { p = p->next; break; } else { q = q->next; m = m->next; } if (!q) return true; } return false;}Dnode *createcirDlink()//尾插法构建循环链表带头结点{ int x; Dnode *h, *t; t = h = (Dnode *)malloc(sizeof(Dnode)); h->rnext = NULL; scanf_s("%d", &x); while (x != -1) { Dnode *s = (Dnode *)malloc(sizeof(Dnode)); s->data = x; s->rnext = h->rnext; t->rnext = s; s->lnext = t; t = s; scanf_s("%d", &x); } t->rnext = h; h->lnext = t; return h;}bool issymmetry17(Dnode *h)//此函数只能判断以头结点为划分两边是否对称,如果一个不带头结点的双循环链表将一个头结点再任意插进某位置则失效{ //基于此改进的方法是,从头结点开始向右遍历,找到一个和其rnext值相等的节点并记录此节点,其分别向左向右依次对 //比如果对比指针相遇则对比成功,如果在对比过程中遇见头结点则要跳过,如果没有相遇且对比失败则从记录的点再次寻找满足和rnext值相等的节点 //当此过程寻找到h的lnext时它的rnext应该为其rnext的rnext; 当所有对比失败并且回到h时则整个判断过程失败 Dnode *lnode = h->lnext; Dnode *rnode = h->rnext; while (!(lnode == rnode || lnode->lnext == rnode)) { if (lnode->data != rnode->data) return false; lnode = lnode->lnext; rnode = rnode->rnext; } return true;}node *createcirlink()//尾插法构建循环链表不带头结点{ int x; node *h, *t; t = h = (node *)malloc(sizeof(node)); h->next = NULL; scanf_s("%d", &x); while (x != -1) { node *s = (node *)malloc(sizeof(node)); s->data = x; s->next = h->next; t->next = s; t = s; scanf_s("%d", &x); } t->next = h;//尾和head相连 return h;//带头结点}node *getcirlinktail(node *h){ node *p = h->next; while (p->next != h) p = p->next; return p;}void printcirlink(node *h){ node *p = h->next; while (p != h) { printf("%d ", p->data); p = p->next; }}void combinecirlink18(node *h1, node *h2){//去掉h2表头将h2最后一个元素连接到h1第一个元素前 node *h2t = getcirlinktail(h2); node *p = h1->next; h2t->next = p; h1->next = h2->next; free(h2); return ;}void delcirminest19(node *h){ //一边寻找最小值一边进行删除这样写时间代价仿佛太大; int min; node *q=h->next; while (q!=h) { min = q->data; node *p = q->next; while (p != h){ if (p->data < min) min = p->data; p = p->next; } while (p->next != h) { if (p->next->data == min) { printf("删除:%d\n", p->next->data); p->next = p->next->next; } p = p->next; } q= h->next; }}typedef struct dnode20{ int data, fre; dnode20 *lnext, *rnext;}Dnode20;Dnode20 *Locate20(Dnode20 *h,type x){ Dnode20 *p=h; Dnode20 *q,*m; while (p->rnext&&p->rnext->data != x) p = p->rnext; if (!p->rnext) return NULL; ++(p->rnext->fre); q = p; m = p->rnext; p->rnext = m->rnext; if (m->rnext!=NULL) m->rnext->lnext = p; while (q!= h&&q->fre <= m->fre) q = q->lnext; q->rnext->lnext = m; m->rnext = q->rnext; m->lnext = q; q->rnext = m; /*q->rnext->lnext = m; p->rnext = m->rnext; m->lnext = q; if (m->rnext) m->rnext->lnext = p; m->rnext = q->rnext; q->rnext = m;*/}void printDnode20(Dnode20 *h);//函数声明Dnode20 *createDnode20link()//创建20题目要求的链表{ type x; Dnode20 *h, *t; t = h = (Dnode20 *)malloc(sizeof(Dnode20)); h->rnext=h->lnext = NULL; scanf_s("%d", &x); while (x != -1) { Dnode20 *s = (Dnode20 *)malloc(sizeof(Dnode20)); s->data = x; s->fre = 0; s->rnext = NULL; t->rnext = s; s->lnext = t; t = s; scanf_s("%d", &x); } t->rnext = NULL; printDnode20(h); return h;}void printDnode20(Dnode20 *h){ Dnode20 *p = h->rnext; while (p) { printf("%d fre:%d ", p->data, p->fre); p = p->rnext; }}
2.3测试用例
int _tmain(int argc, char* argv[]){ node *h1, *h2; // printf("h1为头插法"); //h1 = headinsert(); //printf("%d %d %d",h1->next->data,h1->next->next->data,h1->next->next->next->data); // printf("h2为尾插法"); // printf("%d",h1->next->next->data); //h1 = tailinsert(); // printf("h1:\n"); // print(h1); // printf("h2:\n"); // print(h2); // printf("3在h1的%d号位置,3在h2的%d号位置\n", select(h1, 3), select(h2, 3)); // h1 = del(h1, 3); // h2 = del(h2, 3); // printf("删除3以后h1:\n"); // print(h1); // printf("删除3以后h2:\n"); // print(h2); // printf("在h1的4前添加10,在h2的4后添加10:\n"); // h1 = insert(h1, 4, 10, 0); // printf("h1:\n"); // print(h1); // h2 = insert(h2, 4, 10, 1); // printf("h2:\n"); // print(h2); // printf("将h1就地倒置:\n"); // reverse(h1); // print(h1); // printf("删除h2中的所有重复元素后:\n"); // pur_linklist(h2); // print(h2); // printf("求集合运算h1-h2后的h1:\n"); // difference(h1, h2); // print(h1); // printf("h1交换结点冒泡排序后:\n"); // bubblesort1(h1); // print(h1); // printf("h1交换结点值冒泡排序后:\n"); // bubblesort2(h1); // print(h1); // printf("h2交换结点值冒泡排序后:\n"); // bubblesort2(h2); // print(h2); // printf("h1与h2合并后:\n"); // linkcombine(h1,h2); //recursiondel1(h2->next,3); // r_print(h2->next); // delminest4(h2); // delvalue7(h2,2,5); // posprint9(h2); // resolve10(h2->next,h1) ; // print(h2); // print(h1); //h1 = tailinsert(); //print(combineneg13(h1, h2)); //h2 = tailinsert(); //comele(h1,h2); //print(h1); // printf("%d",issonsequen16(h1,h2)); //node *cirh1 = createcirlink(); /*node *cirh2= createcirlink(); combinecirlink18(cirh1, cirh2); printcirlink(cirh1);*/ //printf("%d", issymmetry17(h)); //delcirminest19(cirh1); Dnode20 *h=createDnode20link(); Locate20(h, 1); printDnode20(h); Locate20(h, 2); printDnode20(h); Locate20(h, 3); printDnode20(h); Locate20(h, 5); printDnode20(h); Locate20(h, 5); printDnode20(h); Locate20(h, 5); printDnode20(h); Locate20(h, 5); printDnode20(h); Locate20(h, 5); printDnode20(h); Locate20(h, 7); printDnode20(h); getchar(); getchar(); return 0;}
第3章
3.3
// 王道考研3.3.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<stdio.h>#include<stdlib.h>#include<cstring>#define max 50;typedef char type;typedef struct{ type data[50]; int top;}stack;void initialstack(stack *s){ s->top = 0;}int push(stack *s, type x){ if (s->top == 50) return -1; s->data[s->top++] = x; return 0;}type pop(stack *s){ if (s->top == 0) return -2; type x = s->data[--s->top]; return x;}//3.36void kuohaomatch1(){ //基本思想扫描每一个字符,遇到花中圆的左括号进栈,遇到花中圆的右括号时检查是否为相应的左括号若不是则匹配失败 char s[50]; int i = 0; char d = 'a'; scanf_s("%c", &d); while (d != ' '&&i<50) { s[i++] = d; scanf_s("%c", &d); } s[i] = '\0'; stack *s1 = (stack *)malloc(sizeof(stack)); stack *s2 = (stack *)malloc(sizeof(stack)); initialstack(s1); initialstack(s2); for (i = 0; s[i] != '\0'; i++) switch (s[i]) { case'{':push(s1, '}'); break; case'(':push(s1, ')'); break; case'[':push(s1, ']'); break; default: if (pop(s1) != s[i]) printf("不匹配"); else printf("匹配"); } printf("匹配"); getchar(); getchar();}int count3(){//基本思想:由P0,P1的值可以直接得到P2的值,根据P1,p2的值可以得到P3的值,依次类推 int n, x; stack *s1 = (stack *)malloc(sizeof(stack)); initialstack(s1); scanf_s("%d %d",&n,&x); if (n == 0) return 1; else if (n == 1) return 2 * x; else { for (int i = 0; i <=n;i++) { if (i == 0) push(s1, 1); else if (i == 1) push(s1, 2*x); else { int tem1 = pop(s1); int value = 2 * x*tem1 - 2 * (i - 1)*pop(s1);//当i=2时,出P0,P1的值,算出P2的值,再将P1,P2的值进栈方便算P3的值 printf("value:%d ", value); //最先出栈的值应保存下来,与计算出来的新值先后压入栈; push(s1, tem1); push(s1, value); } } } return 2 * x*pop(s1) - 2 * (n - 1)*pop(s1);//最后栈顶的值分别是Pn-1与Pn-2}
第四章
4.3
// 王道考研第4章.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<stdio.h>#include<malloc.h>#include<stdlib.h>#include"stack.h"#include "queue.h"//4.3//定义并使用栈//创建二叉树 void creatTree(Tnode *&p)//以先序输入顺序作为节点创建二叉树{ char ch; scanf_s("%c", &ch); if (ch == '.'){ p = NULL; return; } p = (Tnode*)malloc(sizeof(Tnode)); p->data = ch; creatTree(p->lnode); creatTree(p->rnode); return;}void pretraverse(Tnode *root)//先序遍历{ if (!root) return; printf("%c ", root->data); pretraverse(root->lnode);//后序中序则交换这三条语句 pretraverse(root->rnode); return;}void backtraverse(Tnode *root)//后序遍历{ if (!root) return; backtraverse(root->lnode);//后序中序则交换这三条语句 backtraverse(root->rnode); printf("%c ", root->data); return;}void midtraverse(Tnode *root)//中序遍历{ if (!root) return; midtraverse(root->lnode);//后序中序则交换这三条语句 printf("%c ", root->data); midtraverse(root->rnode); return;}void back_order_non_recursion_traverse3(Tnode *t)//后序非递归遍历二叉树{//实现思想:先进栈走到最左边,则访问此节点,如果此节点还有右子树并且没有被访问过则进入右子树,以其为根节点重复上述操作,进栈走到最右边访问该节点 //再出栈,判断栈顶结点是否刚从右子树上返回来,如果是则访问该节再出栈,继续上述判断,如果不是,则进入右子树。 //也可以加上一个标识域记录是否被访问过 stack *s = (stack *)malloc(sizeof(stack)); Tnode *p = t; Tnode *tem = NULL; initialstack(s); while (p || !isemty(s)) { if (p) { push(s, p); p = p->lnode;//走到最左边 } else { p = s->data[(s->top) - 1]; if (p->rnode&&p->rnode != tem) { p = p->rnode; push(s, p); p = p->lnode;//走到最右边 } else { p = pop(s); printf("%c ", p->data); tem = p; p = NULL; } } /* else { loop:if (!isemty(s)&&(p = s->data[(s->top) - 1]->rnode)) continue; else { loop2:{ if (isemty(s)) break; printf("%c ", s->data[s->top - 1]->data); } if (!isemty(s)&&(pop(s) == s->data[(s->top) - 1]->rnode)) goto loop2; goto loop; } } } printf("\n");*/ }}void mid_order_non_recursion_traverse(Tnode *t)//中序非递归遍历二叉树{ //基本思想使用一个栈如果没有遇到空指针则一直左子树根节点入栈,否则就访问该节点并退栈并再访问父节点再遍历 stack *s = (stack *)malloc(sizeof(stack)); Tnode *p = t; Tnode *tem; initialstack(s); while (p || !isemty(s)) { if (p) { push(s, p); p = p->lnode; } else { tem = pop(s); printf("%c ", tem->data); p = s->data[s->top]; p = p->rnode; } } printf("\n");}void pre_order_non_recursion_traverse(Tnode *t)//先序非递归遍历二叉树{ stack *s=(stack *)malloc(sizeof(stack)); Tnode *p = t; Tnode *tem; initialstack(s); while (p || !isemty(s)) { if (p) { printf("%c ", p->data); push(s, p); p = p->lnode; } else{ tem = pop(s); p = tem->rnode; } } printf("\n");}void traverse4(Tnode *root){ //思路:使用队列,先访问右孩子再访问左孩子,并都入队,并再按出队顺序访问右孩子再访问左孩子,并依次入队,并再按出队顺序访问右孩子再访问左孩子。如此反复 queue *q=(queue*)malloc(sizeof(queue)); initqueue(q); Tnode *r=root; pushqueue(q, r); do { Tnode *tem = popqueue(q); printf(" %c ", tem->data); if (tem->rnode) pushqueue(q, tem->rnode); if (tem->lnode) pushqueue(q, tem->lnode); } while(!isqueueemty(q));}int treedepth5(Tnode *root)//非递归{ //利用上题目的方法,每次入每层最右元素时,标记,如果刚刚出队的是最右结点那么就应发出信 //号让下次进队的结点成为下层最右孩子,因为进队的可能是左孩子或右孩子,所以进队时都应该判断,进队后将信号关闭 //开始时最右结点是根节点 queue *q = (queue*)malloc(sizeof(queue)); initqueue(q); Tnode *r = root; Tnode *flag = root; int depth = 0; int biaozhi = 0; if (!root) return 0; pushqueue(q, r); do { Tnode *tem = popqueue(q); if (flag == tem) { depth++;//发现出队的是最右孩子,所以表名这一层存在故加1 biaozhi = 1; } if (tem->rnode) { pushqueue(q, tem->rnode); if (biaozhi) { flag = tem->rnode; biaozhi = 0;//关掉标志 } } if (tem->lnode) { pushqueue(q, tem->lnode); if (biaozhi) { flag = tem->lnode; biaozhi = 0; } } } while (!isqueueemty(q)); return depth;}Tnode *createtree6(char a[], int n1,int m1,char b[],int n2,int m2){ //根据先序和中序遍历结果创建唯一确定的二叉树,递归进行,每次划分数组序列,确定左子树和右子树的结点集合,直至每个集合里的元素只有一个时,可以建立一个树 //b为中序序列,a为先序序列 //设计思路:如果a,b的长度不相等或者两个长度都为0则返回出错 //以先序序列a的首结点为根节点,再在中序序列中找到此节点,左边部分是根节点的左子树节点,右半部分是根节点的右子树节点。故可以采用递归的方法建树 //因此若要进行划分就要输入上界与下界。 //if(a.len != b.len || a.len == 0) //return -1; Tnode *root = (Tnode *)malloc(sizeof(Tnode)); if (root)//分配动态空间成功 root->data = a[n1]; else exit(-1); int i,llen,rlen; i = llen = rlen = 0; for (; b[i] != a[n1]; i++);//找到根节点在中序序列的下标i; llen = i - n2;//说明要以当前root为根节点对需要建树的序列b左子树长 rlen = m2 - i;//说明要以当前root为根节点对需要建树的序列b右子树长 if (llen&&(root->lnode = createtree6(a, n1+1, n1+llen, b, n2, n2+llen-1) ));//当左子树长不为零时建左子树 else root->lnode = NULL;//新的建树序列(新的中序序列)对应b的起始下标n2,结束下标n2+len-1;新的参考序列(新的先序序列)对应a的起始坐标n1+1,结束坐标n1+len; if(rlen && (root->rnode = createtree6(a,m1-rlen+1, m1, b, m2-rlen+1, m2)));//当右子树长不为零时建右子树 else root->rnode = NULL;//新的建树序列(新的中序序列)对应b的起始下标m2-rlrn+1,结束下标m2;新的参考序(新的先序序列)列对应a的起始坐标m1-rlen+1,结束坐标m1; return root;}Tnode *norecur_createtree6(char a[], int alen, char b[]){//此算法经过最终测试,对于大多数的实例都有完美的准确度,不过是非平衡树的时候就会出错。//改进思路:在判断出其左孩子和右孩子为空后记录个数,并将其补为完全二叉树,根据下标对应关系赋值 Tnode *root[7]; for (int i = 0; i < alen; i++) { root[i] = (Tnode *)malloc(sizeof(Tnode)); if (root[i])//分配动态空间成功 { root[i]->data = a[i]; root[i]->lnode = root[i]->rnode=NULL; } else exit(-1); } int i = 0; while (i<alen-1) { int k = 0; int j = 0; int m = 0; int save; int tem; for (; b[k] != a[i + 1]; k++); for (; b[j] != a[i]; j++); if (i == 0) save = j; //给根节点创建左子树 int flag = 0; if (j>k) { root[i]->lnode = root[i+1]; } else { root[i]->lnode = NULL; flag = 1;//说明其左子树为空 } //给根节点创建右子树 for (tem = (i > save ? j+1: j + 1 + i); b[m] != a[tem]; m++); if (m > j&&!flag&&m<alen) { root[i]->rnode = root[tem]; } else if (flag&&a[i+1]==b[j+1])//如果左子树为空再判断中序和前序序列中当前节点的下一个节点是否一致,如果是,说明下一个节点就是其右孩子,如果不是则说明其没有右孩子 root[i]->rnode = root[1 + i]; else root[i]->rnode = NULL; i++; } return root[0];}int treedepth_recursion5(Tnode *root)//递归形式{ if (root== NULL) return 0; else return treedepth_recursion5(root->lnode)>treedepth_recursion5(root->rnode) ? treedepth_recursion5(root->lnode) + 1 : treedepth_recursion5(root->rnode) + 1; }bool isperfect7(Tnode *root){ //采用二叉树的自顶向下,自左向右的层次遍历算法 if (!root) return true;//空树是完全二叉树 queue *q = (queue *)malloc(sizeof(queue)); initqueue(q); pushqueue(q, root);; while (isqueueemty(q)) { if (Tnode *tem=popqueue(q))//首先将第一层的入队,出第一层,其次第二层入队,依次重复,再出某一层时如果某个元素是空,则检查其队后的元素是否都为空 { //利用这样的出队如对算法总能保证某一时刻队列中只含有从左向右的某一行元素,在将这一行元素从左向右依次出栈并入其左孩子右孩子的时候, //如果发现这一行的元素在出队的时候有空,则应该保证队列中全为空元素,如果不是则说明处在同一行的左边某个元素存在孩子, //或说明处在同一行的右边还有非空结点说明非完全二叉树 pushqueue(q, tem->lnode); pushqueue(q, tem->rnode); } else while (!isqueueemty(q)) if (popqueue(q)) return false; } return true;}int doublebranchcount8(Tnode *root){//思路1:采用遍历算法遍历每一个结点,如果它既存在左孩子又存在右孩子则对应一个双分支 if (!root) return 0; if (root->lnode&&root->rnode) return doublebranchcount8(root->lnode) + doublebranchcount8(root->rnode) + 1;//以下可以直接替换为else return doublebranchcount8(root->lnode) + doublebranchcount8(root->rnode) else if (root->lnode) //在逻辑上是等价的当传空根节点时返回0; return doublebranchcount8(root->lnode); else if (root->rnode) doublebranchcount8(root->rnode); else return 0;}void swaplrtree9(Tnode *root){ //思路:考虑用递归进行 Tnode *tem = root->lnode; root->lnode = root->rnode; root->rnode = tem; if (root->lnode) swaplrtree9(root->lnode); if (root->rnode) swaplrtree9(root->rnode);}int count = 1; char getvalue10(Tnode *root, int k){ char ch; if (!root) return '#'; else if (count++ == k) return root->data; else if ( (ch = getvalue10(root->lnode, k)) != '#')//注意赋值号的优先级低 return ch; else return getvalue10(root->rnode, k);}void del_release11(Tnode *root,char k){ //应该采取后序遍历的方式 if (!root) return; if (root->data == k) { if (root->lnode) del_release11(root->lnode, k); else free(root->lnode); if (root->rnode) del_release11(root->rnode,k); else free(root->rnode);}}int countpre(Tnode *root, int dep){ static int wpl = 0;//递归调用时不会重新赋值 //大写A:65小写a:97 0对应48 if (root->lnode) countpre(root->lnode, dep + 1); if (root->lnode == NULL&&root->rnode == NULL) wpl += dep*((int)root->data - 48);//结果表示无论先序后序中序值一样 if (root->rnode) countpre(root->rnode, dep + 1); return wpl;}int wpl20(Tnode *root){ return countpre(root, 0);}int non_recursewpl20(Tnode * root)//可以参考哈夫曼树的创建过程{//关键应知道现在处于第几层即深度是多少 //由先进队再出队进其左右孩子的算法可知,总存在某一时刻,队列中只有是某一层的所有元素 //在某时刻队列只有某层所有元素时,此时就应该注意,从这层首节点到尾结点每次出队再进其 //左右孩子的过程中,如果进入的都是null,说明此节点是叶子节点,就应该给wpl累加 Tnode *pre=root;//进入某层时的最左点 Tnode *last = root;//某层的最右点 Tnode *uplast = NULL;//在下一深层预判最右点的位置 Tnode *preflag = NULL;//在下一深层预判最左点的位置 queue *q=(queue *)malloc(sizeof(queue));//创建队列 int wpl = 0; //初始化wpl int depth = 0; //初始化深度 int flag = 0; //队列是否只有某一层的全部元素(包括null结点)标志 int preflag1 = 1; //是否允许寻找深层最左点标志 initqueue(q); //初始化队列 if (!root) return 0; //如果树空wpl=0; pushqueue(q, root); //先将根节点入队 while (!isqueueemty(q)) //判定对空,将保证二叉树所有结点(包括null结点)都出队一次,直至全部出队完 { Tnode *tem = popqueue(q); //取队头tem if (tem) //若tem非null { //printf("%c ", tem->data); if (tem == pre->lnode) //如果出的pre结点的左孩子 { pre = pre->lnode; depth ++; preflag1 = flag = 1;//那么该节点就为新层最左点,深度增,且此时队列只有该层所有结点(包括空结点),并允许预判下层最左点 } if ((!pre->lnode)&&tem == pre->rnode)//如果出的是pre右孩子且pre左孩子为空,那么该节点就为新层最左点,深度增,此时队列只有该层所有结点(包括空结点),并允许预判下层最左点 { pre = pre->rnode; depth++; preflag1 = flag = 1; } if (tem == preflag)//如果出的是预测最左点,此情况只有在下层最左点与上层最左点没有直接祖先时发生 { pre = tem; depth++; preflag1 = flag = 1; } if ((!pre->lnode)&&(!pre->rnode)&&(tem != pre)&&preflag1)//如果新赋值的最左点没有孩子就应该小心,就要为他找下层最左点 { if (tem->lnode) { preflag = tem->lnode;//一旦遇见下层最左点就应将允许预测最左点标志关闭,并且先判断左孩子再判断右孩子 preflag1 = 0; } if (tem->rnode) { preflag = tem->rnode; preflag1 = 0; } } if (flag == 1){//此时队列在将该层所有结点依次出队(包括空结点),此时就应注意,该层有没有叶子节点 if ((!tem->lnode)&&(!tem->rnode))//如果有应该累加wpl wpl += ((int)(tem->data) - 48)*depth; if (tem->lnode)//并且一直预判下层最右点,只要从这层开始,右边结点右孩子就应该被替换,并且先左孩子再右孩子 uplast = tem->lnode; if (tem->rnode) uplast = tem->rnode; } pushqueue(q, tem->lnode);//将出队结点的孩子入队 pushqueue(q, tem->rnode); if (tem == last->rnode)//如果出队的是上层最右点的右孩子,说明该层依次出队操作完成,应关闭flag标志,且该节点为新的最右 { last = last->rnode; flag = 0; } if ((!last->rnode) && last->lnode == tem)//若上层最右结点没有右孩子而有左孩子且出队的是上层最右点的左孩子,说明该层依次出队操作完成,应关闭flag标志,且该节点为新的最右 { last = last->lnode; flag = 0; } if ((!last->lnode) && (!last->rnode) && tem == last)//如果出的是预测最左点,此情况只有在下层最右点与上层最右点没有直接祖先时发生 { last = uplast; flag = 0;//因为一直在预测下层最右点,而这层最右点没有孩子,那么在出这层最右点时就应该直接将last修改为预测最右点 } } } return wpl; }
4.3测试用例:
int _tmain(int argc, _TCHAR* argv[]){ Tnode* root = NULL; creatTree(root); //abd.g...ceh...f.ij..kl..m..创建二叉树 /*pretraverse(root); printf("\n"); midtraverse(root); printf("\n"); backtraverse(root); printf("\n"); pre_order_non_recursion_traverse(root); mid_order_non_recursion_traverse(root); back_order_non_recursion_traverse3(root);*/ //traverse4(root); //printf("深度:%d",treedepth(root)); /*char a[] = "ABDGHECKFIJ"; char b[] = "GDHBEAKCIJF";*/ //root = createtree6(a, 0, 7, b, 0,7); //root = createtree6(a, 0, 10, b, 0, 10); //swaplrtree9(root); pretraverse(root); printf("\n"); midtraverse(root); //printf("%d ", doublebranchcount8(root)); //char ch = getvalue10(root, 8); printf("%d ",non_recursewpl20(root)); system("pause"); return 0;}
阅读全文
2 0
- 2018
- 2018
- poj 2018
- hdu 2018
- hdu 2018
- HDUOJ 2018
- hdu 2018
- poj 2018
- HDU 2018
- hdu-2018
- HDU 2018
- [HDOJ]2018
- poj 2018
- HDU 2018
- HDU--2018
- HDU-2018
- HDU 2018
- HDOJ--2018
- 通过原生JS和CSS制作钟表
- Scrapy--使用phantomjs爬取花瓣网图片
- android Material Design设计规范
- machine-learning-ex2
- 解决androiStudio无法实现Alt+Insert快捷键弹出窗口
- 2018
- java多线程复习所感
- 17 10 29 成果
- 面向对象总结
- UVA
- golang 整数常量INT_MAX INT_MIN最大值最小值
- 手算KMP匹配的Next值与Nextvul值
- c/c++ 开发中常见的坑
- CentOS 7 防火墙设置