第二章-线性表
2-1-搜索整个顺序表,查找最小值元素并记住其位置,搜索结束后用最后一个元素填补空出的原最小值元素的位置。
bool Del_Min(Sqlist &L, int &value){
if(L.length == 0) return;
value = L.data[0];
int pos = 0;
for(i=1; i<L.length; i++){
if(L.data[i] < value){
value = L.data[i];
pos = i;
}
}
L.data[pos] = L.data[L.length-1];
L.length--;
return true;
}
2-2-顺序表L所有元素逆置,空间复杂度为O(1)
void reverse(SqList &L){
int temp;
for(int i=0; i<(L.length)/2; i++){
temp = L.data[i];
L.data[i] = L.data[L.length-i-1];
L.data[L.length-i-1] = temp;
}
}
2-3-顺序表删除所有值为x的数据元素,时间复杂度O(n),空间复杂度O(1)
void del_all_x(SqList &L, int x){
int k=0;
for(int i=0; i<L.length; i++){
if(L.data[i] != x){
L.data[k++] = L.data[i];
}
}
L.length = k;
}
2-4-有序顺序表中删除给定值 s 与 t 之间的所有元素
bool del_s_t(SeqList &L, int s, int t){
if(L.length == 0 || s>=t){
return false;
}
for(int i=0; i<L.length&&L.data<s; i++);
if(i>=L.length) return false;
for(j=i; j<L.length&&L.data[j]<=t; j++);
for(; j<L.length; j++){
L.data[i++] = L.data[j];
}
L.length = i;
return true;
}
2-5-从顺序表中删除给定值s与t之间的所有元素。
bool del(SqList &L, int s, int t){
if(L.length==0 || s>t) return false;
for(int i=0; i<L.length; i++){
if(L.data[i]>=s && L.data[i]<=t){
k++;
}
else{
L.data[i-k] = L.data[i];
}
}
L.length -=k;
return true;
}
2-6-有序顺序表中删除所有值重复的元素,使所有元素的值均不同
bool del_same(SeqList &L){
int i, j;
for(i=0,j=1; j<L.length; j++){
if(L.data[i] != L.data[j]){
L.data[++i] = L.data[j];
}
}
L.length = i+1;
return true;
}
2-7-两个有序顺序表合并为一个新的有序顺序表,由函数返回结果顺序表
bool merge(SeqList A, SeqList B, SeqList &C ){
if(A.length + B.length > C.length) retrun false;
int i=0,j=0,k=0;
while(i<A.length && j<B.length){
if(A.data[i] < B.data[j]){
C.data[k++]=A.data[i++];
}
else
C.data[k++]=B.data[j++];
}
while(i<A.length){
C.data[k++] = A.data[i++];
}
while(j<B.length){
C.data[k++] = B.data[j++];
}
C.length = k;
return true;
}
2-8-一维数组 A[m+n] 中将两个顺序表m和顺序表n 的位置互换
void reverse(int A[], int left, int right, int arraysize){
int temp;
if(left >= right || right>=arraysize) return;
int mid = (left + right) / 2;
for(int i=0; i<mid-left; i++){
temp = A[left + i];
A[left + i] = A[right - i];
A[right - i] = temp;
}
}
void exchange(int A[], int left, int right, int arraysize){
reverse(A, 0, m+n-1, arraysize);
reverse(A, 0, n-1, arraysize);
reverse(A, n, m+n-1, arraysize)
}
2-9-递增有序顺序表,查找数值为 x 的元素。若找到则与其后继元素交换位置,找不到则将其插入表中。
void serach(int A[], int x){
int low=0, high=n-1, temp;
while(low < high){
int mid = (low+high)/2;
if(A[mid] = x)
break;
else if(A[mid] > x)
high = mid - 1;
else
low = mid + 1;
}
if(A[mid] == x && mid != n-1){
temp = A[mid];
A[mid] = A[mid + 1];
A[mid + 1] = temp;
}
if(low > high){
for(i=n-1; i>high; i--)
A[i+1] = A[i];
A[i+1] = x;
}
}
2-10一维数组R的序列循环左移p个位置,空间和时间上都尽量高效。
void reverse(int R[], int left, int right){
int temp;
int mid = (left + right) /2;
for(int i=0; i<mid-left; i++){
temp = R[left + i];
R[left + i] = R[right - i];
R[right - i] = temp;
}
void exchange(int R[], int left, int right){
reverse(R, 0, p-1);
reverse(R, p, n-1);
reverse(R, 0, n-1);
}
}
2-11-找出两个有序序列的中位数并返回
int search_middle(int A[], int B[]){
int c[length(A)+length(B)]={0};
int i,j,k;
while(i<A.length&&j<B.length){
if(A[i]<B[j])
C[k++] = A[i++];
else
C[k++] = B[j++];
}
while(i<A.length){
C[k++] = A[i++];
}
while(j<B.length){
C[k++] = B[j++];
}
return C[C.length/2];
}
2-12-设计一种尽可能高效的算法找出A的主元素
int majority(int A, int n){
int c,count=0;
c=A[0];
for(int i=0; i<n; i++){
if(A[i] == c){
count++;
}
else
if(count > 0)
count--;
else{
c=A[i];
count=1;
}
}
if(count>0){
for(int i=count=0; i<n; i++){
if(A[i] == c)
count++;
}
}
if(count > n/2)
return c;
else
return -1;
}
2-13-找出数组中未出现的最小正整数,时间上尽可能高效。
int find_Min(int A[], int n){
B = (int*) malloc(sizeof(n));
for(int i=0; i<n; i++){
B[i]=0;
}
for(int i=0; i<n; i++){
if(A[i]>=1 && A[i]<=n){
B[A[i]-1] = 1;
}
}
for(int i=0; i<n; i++){
if(B[i] == 0){
break;
}
}
return i+1;
}
2-14 设计一个递归算法,不带头结点的单链表L删除所有值为x的结点
void del_x(LinkList &L, int x){
LNode *p;
if(L==null)
return;
if(L->data == x){
p = L;
L = L->next;
free(p);
del_x(L,x);
}
else{
del_x(L->next,x);
}
}
2-15-带头结点的单链表L删除所有值为 x 的结点,释放其空间,假设值 x 的结点不唯一
void del_x(LinkList &L, int x){
LNode *pre=L, *q;
LNode *p=L->next;
while(p!=null){
if(p->data == x){
q=p;
p=p->next;
pre->next=p;
free(q);
}
else{
pre=p;
p=p->next;
}
}
}
2-16-带头结点的单链表L逆向输出每个结点的值
void reverse(LinkList &L){
Stack s;
InitStack(s);
LNode *p=L->next;
while(p!=null){
push(S, p->data);
p=p->next;
while(p->next=null&&!StackEmpty(s)){
pop(s, p);
printf("%d",p->data);
}
}
}
2-17-带头结点的单链表L中删除最小值结点(假设最小值结点唯一),时间高效
LinkList del_min(LinkList &L){
LNode *pre=L, *p=pre->next;
LNode *minpre=pre, *minp=p;
while(p!=null){
if(p->data < minp->data){
minp = p;
minpre = pre;
}
pre=p;
p=p->next;
}
minpre->next = minp->next;
free(minp);
return L;
}
2-18- 带头结点的单链表就地逆置,即辅助空间复杂度为O(1)。
LinkList reverse(LinkList &L){
LNode *p=L-next, *r;
L->next=null;
while(p != null){
r=p->next;
p-next = L->next;
L->next = p;
p=r;
}
return L;
}
2-19- 带头结点的单链表L使其元素递增有序
void sort(LinkList &L){
LNode *p=L->next, *pre;
r=p->next;
p->next=null;
p=r;
while(p!=null){
r=p->next;
pre=L;
while(pre->next!=null && pre->next->data<p->data){
pre=pre->next;
}
p->next=pre->next;
pre->next=p;
p=r;
}
}
2-20- 带头结点的单链表L无序,删除表中所有介于给定的两个值之间的元素(若存在)
LinkList del(LinkList &L, int m, int n){
LNode *p=L->next, *pre=L;
while(p != null){
if(p->data >m && p-data<n){
pre->next = p->next;
free(p);
p=pre->next;
}
pre=p;
p=p->next;
}
return L;
}
2-21-找出两个链表的公共结点
LinkList search(LinkList L1, LinkList L2){
LNode *longList, *shortList;
int len1=length(L1);
int len2=length(L2);
int dist;
if(len1 > len2){
longList=L1->next;
shortList=L2->next;
dist=len1-len2;
}
else{
longList=L2->next;
shortList=L1->next;
dist=len2-len1;
}
while(dist--){
longList=longList->next;
}
while(longList){
if(longList=shortList)
return longList;
else{
longList=longList->next;
shortList=shortList->next;
}
}
return null;
}
2-22-带头结点的单链表,head为头指针,递增输出数据元素,并释放结点存储空间。(不允许使用数组作为辅助空间)
void increasing_print(LinkList &head){
while(head->next !=null){
LNode *pre=L, *p=pre->next, *q;
while(p->next!=null){
if(p-next->data<pre->next->data)
pre=p;
p=p->next;
}
printf("%d",pre->next->data);
q=pre->next;
pre->next=q->next;
free(q);
}
free(head);
}
2-23-带头结点的单链表A分解为使A表中含有原表中序号为奇数的元素,B表中含有原表中序号为偶数的元素,相对顺序保持不变。
LinkList dis_chart(LinkList &A){
LinkList B=(LNode*)malloc(sizeof(LNode));
B->next=null;
LNode *ra=A, *rb=B, *p=A->next;
A->next=null;
int i=0;
while(p!=null){
i++;
if(i%2==0){
rb->next=p;
rb=p;
}
else{
ra-next=p;
ra=p;
}
p=p->next;
}
ra-next=null;
rb->next=null;
return B;
}
2-24-带头结点的单链表A={a1,b1,a2,b2······am,bn}拆解为两个线性表,使得A={a1,a2···an},B = {bm,····b2,b1}
LinkList dis_chart(LinkList &A){
LinkList B=(LNode*)malloc(sizeof(LNode));
B->next=null;
LNode *ra=A, *p=A->next, *q;
A->next=null;
while(p!=null){
ra->next=p;
ra=p;
p=p->next;
if(p!=null){
q->p->next;
p->next=B->next;
B->next=p;
p=q;
}
}
ra->next=null;
return B;
}
2-25-递增的单链表,去掉表中重复的元素,只保留一个数值
LinkList del_same(LinkList &L){
LNode *p=L->next, *q;
while(p!=null){
q=p->next;
if(p->data=q->data){
p->next=q->next;
free(q);
}
else{
p=p->next;
}
}
return L;
}
2-26-两个递增的单链表归并为一个递减的单链表,并要求利用原来两个单链表的结点存放归并后的单链表
void MergeList(LinkList &La, LinkList &Lb){
LNode *pa=La->next, *pb=Lb->next, *r;
La->next=null;
while(pa&&pb){
if(pa->data < pb->data){
r=pa->next;
pa->next=La->next;
La->next=pa;
pa=r;
}
else{
r=pb->next;
pb->next=La->next;
La->next=pb;
pb=r;
}
}
if(pa){
pb=pa;
}
while(pb){
r=pb->next;
pb->next=La->next;
La->next=pb;
pb=r;
}
free(Lb);
}
2-27-两个带头结点并且递增的单链表A和B中产生单链表C,C中包含它们的公共元素,要求不破坏A、B的结点
LinkList search_com(LinkList A, LinkList B){
LNode *pa=A->next, *pb=B->next, *r, *s;
LinkList C=(LNode*)malloc(size(LNode));
C->next=null;
r=C;
while(pa&&pb){
if(pa->data<pb->data){
pa=pa->next;
}
else if(pb->data<pa->data){
pb=pb->next;
}
else{
s=(LNode*)malloc(sizeof(LNode));
s->data=pa->data;
s->next=r->next;
r->next=s;
r=s;
pa=pa->next;
pb=pb->next;
}
}
r->next=null
return C;
}
2-28两个递增的单链表A和B,将A和B的公共元素存放于A链表中
LinkList Union(LinkList &A, LinkList &B){
LNode *pa=A->next, *pb=B->next, *r, *q;
A->next=null;
r=A;
while(pa&&pb){
if(pa->data==pb->data){
pa->next=r->next;
r->next=pa;
r=pa;
pa=pa->next;
q=pb;
pb=pb->next;
free(pb);
}
else if(pa->data<pb->data){
q=pa;
pa=pa->next;
free(q);
}
else{
q=pb;
pb=pb->next;
free(q);
}
}
while(pa){
q=pa;
pa=pa->next;
free(q);
}
while(pb){
q=pb;
pb=pb->next;
free(q);
}
r->next=null;
return A;
}
2-29-判断单链表B中的序列是否是单链表A中序列的连续子序列
int Pattern(LinkList A, LinkList B){
LNode *pa=A, *pb=B, *pre=pa;
while(pa&&pb){
if(pa->data=pb->data){
pa=pa->next;
pb=pb->next;
}
else{
pre=pre->next;
p=pre;
pb=B;
}
}
if(pb==null) return 1;
else return 0;
}
2-30-判断带头结点的循环双链表是否对称
int Symmetry(DLinkList L){
DNode *p=L->next, *q=L->prior;
while(p!=q && q->next=p){
if(p->data == q->data){
p=p->next;
q=q->prior;
}
else
return 0
}
return 1;
}
2-31-将循环单链表h2链接到h1之后,要求链接后的链表仍保持循环链表形式
LinkList link(LinkList &h1, LinkList &h2){
LNode *p=h1, *q=h2;
while(p->next != h1)
p=p->next;
while(q->next != h2)
q=q->next;
p->next=h2;
q->next=h1;
return h1;
}
2-32- 带头结点的循环单链表,结点值均为正整数,反复找出结点值最小的结点输出并删除,直到单链表为空,再删除表头结点。
void del_all(LinkList &L){
LNode *p, *pre, *minpre, *minp;
while(L->next != L){
p=L->next;
pre=p;
minpre=pre;
minp=p;
while(p!=L){
if(p->data<minp->data){
minp=p;
minpre=pre;
}
pre=p;
p=p->next;
}
printf("%d",p->data);
minpre->next=minp->next;
free(minp)
}
free(L);
}
2-33-查找链表倒数第 k 个位置上的结点 (k为正整数)。若查找成功,输出该结点的data域的值,并返回1;否则只返回0。(已给出头指针list)
int search_k(LinkList L, int k){
LNode *list=L->next, *q=list;
int count=0;
while(p!=null){
if(count<k){
count++;
}
else{
q=q->next;
}
p=p->next;
}
if(count<k) return 0;
else printf("%d",q->data);
}
2-34-带头结点的单链表保存保存单词,当两个单词有相同的后缀时,可共享相同的后缀存储空间,找出由 str1 和 str2所指向两个链表共同后缀的起始位置。
int len(LNode *head){
int len=0;
while(head->next){
len++;
head=head->next;
}
return len;
}
LNode *find_addr(LNode *str1, LNode *str2){
LNode *p=str1, *q=str2;
m=len(str1);
n=len(str2);
while(m<n){
p=p->next;
}
while(n<m){
q=q->next;
}
while(p->next!=null && p->next!=q->next){
p=p->next;
q=q->next;
}
return p->next;
}
2-35-带头结点的单链表保存 m 个整数,且 |data|<=n,(n为正整数), 对于链表中绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点,时间上尽可能高效。
void func(LinkList &L){
LNode *p=L, *q, *r;
q=(LNode*)malloc(sizeof(LNode));
for(int i=0; i<m; i++){
*(q+i)=0;
}
int n;
while(p->next != null){
if(p->next->data>0)
n=p->next->data;
else
n=-p->next->data;
if(*(q+n)==0)
*(q+n)=1;
else{
r=p->next;
p->next=r->next;
free(r);
}
}
free(q);
}
2-36-判断一个链表是否有环,如果有则返回环的入口地址
LNode *find_loop(LinkList head){
LNode *fast=head, *slow=head;
while(slow && fast->next){
slow=slow->next;
fast=fast->next->next;
if(fast == slow)
break;
}
if(slow==null || fast->next==null)
return null;
LNode *p=head, *q=slow;
while(p!=q){
p=p->next;
q=q->next;
}
return p->next;
}
2-38-设线性表L(a1,a2,a3,…,an-2,an-1,an),采用带有头结点的链表保存,设计尽可能高效的算法重新排列L为L’(a1,an,a2,an-1,…)
LinkList relist(LinkList &head){
LNode *p=head, *q=head, *r, *s;
while(q->next!=null){
p=p->next;
q=q->next;
if(q->next != null)
q=q->next;
}
q=p->next;
p->next=null;
while(q->next!=null){
r=q->next;
q->next=p->next;
p->next=q;
q=r;
}
s=head->next;
q=p->next;
p->next=null;
while(q!=null){
r=q->next;
q->next=s->next;
s->next=q;
q=r;
}
}
第三章-栈、队列
3-1-进栈表示I,出栈表示O,判断一组有IO组成的序列是否合法
int judge(char A[]){
int i=0,j,k;
while(A[i] != '\0'){
switch(A[i]){
case 'I': j++;break;
case'O':k++;
if(k>j)
return 0;
}
i++;
}
if(k!=j)
return 0;
else
return 1;
}
3-2-单链表头指针为L,data域为字符型。判断链表的全部 n 个字符是否中心对称。例如 xyx 是中心对称
int symmetry(LinkList L, int n){
LNode *p=L->next;
int i=0;
char[n/2];
for(i=0; i<n/2; i++){
s[i]=p->data;
p=p->next;
}
i--;
if(n%2!=0)
p=p->next;
while(p&&s[i]=p->data){
i--;
p=p->next;
}
if(i=-1)
return 1;
else
return 0;
}
3-3-编写共享栈的入栈和出栈
#define maxsize 100
typedef struct{
int stack[maxsize];
int top[2];
}stk;
stk s;
int push(int i, int key){
if(i<1 || i>maxsize)
return 0;
if(s.top[1]-s.top[0] == 1)
return 0;
switch(i){
case 0: s.stack[++s.top[0]]=x;return 1;break;
case 1: s.stack[--s.top[1]]=x;return 1;
}
}
int pop(int i){
if(i<1 || i>maxsize)
return 0;
switch(i){
case 0:
if(s.top[0]==-1) return 0;
else return s.stack[s.top[0]--];
break;
case 1:
if(s.top[1]==maxsize) return 0;
else return s.stack[s.top[1]++];
}
}
3-4-栈的括号匹配
bool match(char str[]){
InitStack(S);
int i=0;
while(str[i] != '\0'){
switch(str[i]){
case '(': push(S, '(');break;
case '[': push(S, '[');break;
case '{': push(S, '{');break;
case ')': pop(S, e); if(e != '(') return false; break;
case ']': pop(S, e); if(e != '[') return false; break;
case '}': pop(S, e); if(e != '}') return false; break;
}
i++;
}
if(!StackEmpty(S)) return false;
else return true;
}
3-5-铁道火车调度问题,将所有的软座调度到硬座之前
void train_arrange(char *train){
Stack s;
InitStack(S);
char *p=train, *q=train, c;
while(*p){
if(*p == 'H')
push(s, *p);
else
*(q++)=*p;
p++;
}
while(!StackEmpty(S)){
pop(s, c);
*(q++)=c;
}
}
3-6-利用递归函数实现非递归计算
double p_solution(int n, int x){
struct stack{
int no;
double val;
}st[maxsize];
int top=-1, i;
double fv1=1, fv2=2*x;
for(i=n; i>=2; i--){
top++;
st[top].no=i;
}
while(top>=0){
st[top].val=2*x*fv2-2*(st[top.no-1])*fv1;
fv1=fv2;
fv2=st[top].val;
top--;
}
if(n==0) return fv1;
return fv2;
}
3-7-客货车载渡问题
Queue q
Queue q1
Queue q2
void manager(){
int i, j;
while(j<10){
if(!QueueEmpty(q1) && i<4){
Dequeue(q1,x);
Enqueue(q,x);
i++;
j++;
}
else if(i==4 && !QueueEmpty(q2)){
Dequeue(q2,x);
Enqueue(q,x);
j++;
}
else{
while(j<10&&i<4&&!QueueEmpty(q2)){
Dequeue(q2,x);
Enqueue(q,x);
i++;
j++;
}
i=0;
}
if(QueueEmpty(q1)&&QueueEmpty(q2)) return;
}
}
第五章-树
5-1-一颗采取顺序存储的二叉树,求两个节点的最近公共祖先
int com_ancestor(Sqtree T[], int i, int j){
if(T[i]!='#' && T[j]!='#'){
while(i!=j){
if(i>j)
i=i/2;
else
j=j/2;
}
return T[i];
}
}
5-2-编写后序遍历二叉树的非递归算法
void post_order(BiTree T){
Stack s;
BiNode *p=T, *r=null;
InitStack(s);
while(p || !StackEmpty(s)){
if(p){
push(s,p);
p=p->lchild;
}
else{
getTop(s,p);
if(p->rchild && p!=r){
p=p->rchild;
}
else{
pop(s,p);
visit(p->data);
r=p;
p=null;
}
}
}
}
5-3- 编写二叉树的自下而上、自右到左的层次遍历算法
void level(BiTree T){
BiNode *p=T;
Stack S; Queue(Q);
InitQueue(Q);
InitStack(S);
Enqueue(Q,p);
while(!QueueEmpty(Q)){
Dequeue(Q,p);
push(S,p);
if(p->lchild)
Enqueue(Q,p->lchild);
if(p->rchild)
Enqueue(Q,p->rchild);
}
while(!StackEmpty(S)){
pop(S,p);
visit(p->data);
}
}
5-4-非递归算法求二叉树的高度
int tree_depth(BiTree T){
BiTree q[maxsize];
int rear=-1, front=-1;
int level=0, last=0;
if(!T)
return 0;
q[++rear]=T;
BiTree p;
while(front < rear){
p=q[++front];
if(p->lchild)
q[++rear]=p->lchild;
if(p->rchild)
q[++rear]=p->rchild;
if(front == last){
level++;
last=rear;
}
}
return level;
}
int Btdepth2(BiTree T)
{
if(T==NULL)
return 0;
ldep = Btdepth(T->lchild);
rdep = Btdepth(T->rchild);
if(ldep > rdep)
return ldep+1;
else
return rdep+1;
}
5-5-二叉树各结点的值互不相同,其先序遍历和中序遍历序列分别存于两个一维数组A[1···n]和B[1···n]中,试编写算法建立该二叉树的二叉链表。
BiTree PreInCreat(int A[],int B[],int l1,int h1,int l2,int h2)
{
root = (BiTNode*)malloc(sizeof(BiTNode));
root->data = A[l1];
for(i = l2;B[i]!=root->data;i++);
llen = i - l2;
rlen = h2 - i;
if(llen)
root->lchild = PreInCreat(A,B,l1+1,l1+llen,l2,l2+llen-1);
else
root->lchild = NULL;
return root;
}
5-6-二叉树按二叉链表形式存储,写一个判别给定二叉树是否是完全二叉树的算法。
bool IsComplete(BiTree T)
{
Queue Q;
InitQueue(Q);
if(!T)
return 1;
EnQueue(Q,T);
while(!IsEmpty(Q))
{
DeQueue(Q,p);
if(p)
{
EnQueue(Q,p->lchild);
EnQueue(Q,p->rchild);
}
else
while(!IsEmpty(Q)){
DeQueue(Q,p);
if(p)
return 0;
}
}
return 1;
}
5-7-二叉树按二叉链表形式存储,计算一棵给定二叉树的所有双分支结点个数
int d_node_count(BiTree T){
int cnt=0;
if(!T)
return 0;
if(T->lchild && T->rchild)
cnt++;
cnt += d_node_count(T->lchild);
cnt += d_node_count(T->rchild);
}
5-8-二叉树B按二叉链表形式存储,编写一个树B中所有结点的左、右子树进行交换的函数。
void swap(BiTree &T){
int temp;
if(T != NULL){
swap(T->lchild);
swap(T->rchild);
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
}
}
5-9-二叉树按二叉链表形式存储,求先序遍历序列中第 k (1<=k<=二叉树中结点个数) 个结点的值。
int i=1;
int PreNode(BiTree b,int k)
{
if(b==NULL)
return '#';
if(i==k)
return b->data;
i++;
ch = PreNode(b->lchild,k);
if(ch !='#')
return ch;
ch = PreNode(b->rchild,k);
return ch;
}
5-10-二叉树按二叉链表形式存储,对于树中每个元素值为 x 的结点,删去以它为根的子树,并释放相应的空间。
void DeleteXTree(BiTree bt)
{
if(bt){
DeleteTree(bt->lchild);
DeleteTree(bt->rchild);
free(bt);
}
}
void Search(BiTree bt,int x)
{
BiTree Q[maxsize];
if(bt){
if(bt->data == x){
DeleteXTree(p->lchild);
exit(0);
}
Init Queue(Q);
EnQueue(Q,bt);
while(!IsEmpty(Q)){
DeQueue(Q,p);
if(p->lchild)
if(p->lchild->data == x){
DeleteXTree(p->lchild);
p->lchild = NULL;
}
else
EnQueue(Q,p->lchild);
if(p->rchild)
if(p->rchild->data ==x){
DeleteXTree(p->rchild);
p->rchild = NULL;
}
else
EnQueue(Q,p->rchild);
}
}
}
5-11-二叉树中查找值为 x 的结点,打印值为 x 的结点的所有祖先,假设值为x的结点不多于一个。
typedef struct{
BiTree t;
int tag;
}stack;
void Search(BiTree bt,int x)
{
stack s[];
top = 0;
while(bt!=NULL || top>0)
{
while(bt!=NULL && bt->data !=x)
{
s[++top].t = bt;
s[top].tag = 0;
bt = bt->lchild;
}
if(bt->data ==x)
{
printf("所查结点的所有祖先结点的值为:\n");
for(i=1;i<=top;i++)
printf("%d",s[i].t->data);
exit(1);
}
while(top!=0 && s[top].tag==1)
top--;
if(top!=0)
{
s[top].tag =1;
bt = s[top].t->rchild;
}
}
}
5-12-二叉树按二叉链表形式存储,试求非空二叉树b的宽度 (即具有结点数最多的那一层的结点个数)。
typedef struct(
BiTree data[MaxSize];
int level[MaxSize];
int front,rear;
}Qu;
int BTWidth(BiTree b){
BiTree p;
int k,max,i,n;
Qu.front=Qu.rear= -1;
Qu.rear++;
Qu.data[Qu.rear]=b;
Qu.level[Qu.rear]=1;
while(Qu.front<Qu.rear){
Qu.front++;
p=Qu.data[Qu.front];
k=Qu.level[Qu.front];
if(p->lchild!=NULL){
Qu.rear++;
Qu.data[Qu.rear]=p->lchild;
Qu.level[Qu.rear]=k+1;
}
if(p->rchild!=NULL){
Qu.rear++;
Qu.data [Qu.rear]=p->rchild;
Qu.level[Qu.rear]=k+1;
}
}
max=0;i=0;
k = 1;
while(i<=Qu.rear){
n=0;
while(i<=Qu.rear&6Qu.level[i]==k){
n++;
i++;
}
k=Qu.level[i];
if(n>max) max=n;
}
return max;
}
5-13-设有一棵满二叉树(所有结点值均不同),已知其先序序列为pre,设计一个算法求其后序序列post.
void PreToPost(int pre[],int l1,int h1,int post[],int l2,int h2){
int half;
if(h1>=l1){
post[h2]=pre[l1];
half = (h1-l1)/2;
PreroPost(pre,l1+1,l1+half,post,l2,l2+half-1);
PreroPost(pre,l1+half+1,h1,post,l2+half,h2-1;
}
}
5-14-二叉树按二叉链表形式存储,设计算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为head,链接时用叶结点的右指针域来存放单链表指针。
LinkedList head,pre=NULL;
LinkedList InOrder(BiTree bt){
if(bt){
Inorder(bt->lchild);
if(bt->lchild==NULL && bt->rchild==NULL)
if(pre==NULL){
head=bt;
pre=bt;
}
else{
pre->rchild=bt;
pre=bt;
}
Inorder(bt->rchild);
pre->rchi1d=NULL;
return head;
}
5-15-判断两棵二叉树是否相似的算法,所谓二叉树T1和T2相似,指的是T1和T2都是空的二叉树或都只有一个根节点;或T1的左子树和T2的左子树是相似的,且T1的右子树和T2的右子树是相似的。
int similar(BiTree T1,BiTree T2){
int leftS,rightS;
if(T1==NULL && T2==NULL)
return 1;
else if(T1==NULL||T2==NULL)
return 0;
else{
leftS = similar(T1->lchild,T2->lchild);
rightS = similar(T1->rchild,T2->rchild);
return leftS && rightS;
}
}
5-16-写出在中序线索二叉树里查找指定结点在后序的前驱结点的算法
BiThrTree InPostPre(BiThrTree t,BiThrTree p){
BiThrTree q;
if(p->rtag == 0)
q = p->rchild;
else if(p->ltag ==0)
q = p->lchild;
else if(p->lchild ==NULL)
q = NULL;
else
{
while(p->ltag ==1 && p->lchild!=NULL)
p = p->lchild;
if(p->ltag ==0)
q = p->lchild;
else
q = NULL;
}
return q;
}
5-16-二叉树按二叉链表形式存储,设计求二叉树T的WPL的算法
typedef struct BiTNode{
int weight;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
int WPL(BiTree root){
return wpl_PreOrder(root,0);
}
int wpl_Preorder(BiTree root,int deep){
static int wpl=0;
if(root->lchild==NULL && root->rchild==NULL)
wpl += deep*root->weight;
if(root->lchild !=NULL)
wp1_PreOrder(root->1child,deep+1);
if(root->rchild !=NULL)
wp1_PreOrder(root->rchild,deep+1);
return wpl;
5-17-将给定的表达式(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。
void BtreeToE(BTree *root){
BtreeToExp(root,1);
}
void BtreeToExp(BTree*root,int deep)
{
if(root==NULL) return;
else if(root->left==NULL && root->right==NULL)
printf("%s",root->data);
else{
if(deep>1) printf("(");
BtreeToExp(root->left,deep+1);
printf("%s",root->data);
BtreeToExp(root->right,deep+1);
if(deep>1) printf(")");
}
}
5-18-编程以孩子兄弟表示法存储的森林的叶子结点数
typedef struct node
{
int data;
int node *fch,*nsib;
}*Tree;
int Leaves(Tree t){
if(t==NULL)
return 0;
if(t->fch==NULL)
return 1+Leaves(t->nsib);
else
return Leaves(t->fch)+Leaves(t->nsib);
}
5-19-以孩子兄弟链表为存储结构,请设计递归算法求树的深度
int Height(CSTree bt){
int hc,hs;
if(bt==NULL)
return 0;
else{
hc = height(bt->firstchild);
hs = height(bt->nextsibling);
if(hc+1>hs)
return hc+1;
else
return hs;
}
}
5-20-已知一棵树的层次序列及每个结点的度,编写算法构造此时的孩子-兄弟链接
#define maxNodes 15
void createcSTree_Degree(Csfree&T,int e[],int degree[],int n){
CSNode *pointer = new CSNode[maxNodes];
int i,j,d,k=0;
for(i=0;i<n;i++){
pointer[i]=new csNode;
pointer[i]->data=e[i];
pointer[i]->lchild=pointer[i]->rsibling=NULL;
}
for(i=0;i<n;i++){
d=degree[i];
if(d){
k++;
pointer[i]->1child=pointer[k];
for(j=2;j<=d;j++){
k++;
pointer[k-1]->rsibling = pointer[k];
}
}
T = pointer[0];
delete [] pointer;
}
5-21-判断给定的二叉树是否是二叉排序树
int predt=-32767;
int JudgeBST(BiTree bt){
int b1,b2;
if(bt==NULL)
return 1;
else{
b1=JudgeBST(bt->1child);
if(b1==0 || predt>=bt->data)
return 0;
predt=bt->data;
b2=JudgeBST(bt->rchild);
return b2;
}
}
5-21-设计一个算法,求出指定结点在给定二叉排序树中的层次
int level(BiTree bt,BSTNode *p){
int n=0;
BiTree t=bt;
if(bt!=NULL){
n++;
while(t->data!=p->data){
if(t->data < p->data)
t = t->lchild;
else
t = t->rchild;
n++;
}
}
return n;
}
5-22-利用二叉树遍历的思想编写一个判断二叉树是否平衡二叉树的算法
void Judge AVL(BiTree bt,int &balance,int sh){
int b1=0,br=0,hl=0,hr=0;
if(bt==NULL){
h=0;
balance=1;
}
else if(bt->1child==NULL&6bt->xchild==NULL){
h=1;
balance=1;
}
else{
Judge _AVL(bt->1child,bl,h1);
Judge_AVL(bts>rchild,br,hr);
h=(h1>hr?hl:hr)+1;
if(abs(hl-hr)<2)
balance=bl&&br;
else
balance=0;
}
}
5-23-设计一个算法,求出给定二又排序树中最小和最大的关键字。
int MinKey(BSTNode *bt){
while(bt->lchild != NULL)
bt=bt->lchild;
return bt->data;
}
int MaxKey(BSTNode *bt){
while(bt->rchild != NULL)
bt = bt->rchild;
return bt->data;
}
5-24-设计一个算法,从小到大输出二叉排序树中所有值小于 k 的关键字
void OutPut(BSTNode *bt, int k)
{
if(bt==NULL)
return;
if(bt->rchild != NULL)
OutPut(bt->rchild,k);
if(bt->data >= k)
printf("%d",bt->data);
if(bt->lchild !=NULL)
OutPut(bt->lchild,k);
}
5-25-编写一个递归算法,在一棵有n个结点的、随机建立起来的二又排序树上查找第k (1<k<n) 小的元素,并返回指向该结点的指针。要求算法的平均时间复杂度为O(log2n),二又排序树的每个结点中除data、lchild、rchild等数据成员外,增加一个count成员,保存以该结点为根的子树上的结点个数。
BSTNode *Search_Small(BSTNode*t,int k){
if(k<1 || k>t->count) return NULL;
if(t->lchild==NULL){
if(k==1) return;
else return Search_Small(t->rchild,k-1);
}
else{
if(t->lchild->count == k-1)
return t;
if(t->lchild->count > k-1)
return Search_Small(t->lchild,k);
if(t->lchild->count < k-1)
return Search_Small(t->rchild,k-(t->lchild->count+1));
}
第六章-图
6-1-写出从图的邻接表表示转换成邻接矩阵表示的算法
void Convert(ALGraph &G,int arcs[M][N]){
for(i=0; i<n; i++){
p =(G->v[i]).firstarc;
while(p!=NULL){
arcs[i][p->data]=1;
p=p->nextarc;
}
}
}
6-2-试设计一个算法,判断一个无向图G是否为一棵树。若是一棵树,则算法返回true,否则返回false。
bool isTree(Graph& G){
for(i=1;i<=G.vexnum;i++)
visited[i]=FALSE;
int Vnum=0,Enum=0;
DFS(G,1,Vnum,Enum,visited);
if(Vnum==G.vexnum && Enum==2*(G.vexnum-1))
return true;
else
return false;
void DFS(Graph& G,int v,int& Vnum,int& Enum,int visited[]){
visited[v]=TRUE;
Vnum++;
int w=FirstNeighbor(G,v);
while(w !=-1){
Enum++;
if(!visited[w])
DFS(G,w,Vnum,Enum,visited);
w=NextNeighbor(G,v,w);
}
}
6-3-写出图的深度优先搜索DFS算法的非递归算法(图采用邻接表形式)。
void DFS_Non_RC(AGraph& G,int v){
int w;
InitStack(S);
for(i=0; i<G.vexnum; i++)
visited[i]=FALSE;
Push(S,v); visited[v]=TRUE;
while(!IsEmpty(S)){
k=Pop(S);
visit(k);
for(w=FirstNeighbor(G,k); w>=0; w=NextNeighor(G,k,w))
if(!visited[w]){
Push(S,w);
visited[w]=true;
}
}
}
6-4-分别采用基于深度优先遍历和广度优先遍历算法判别以邻接表方式存储的有向图中是否存在由顶点 vi 到顶点 vj 的路径 (i≠j) 。注意,算法中涉及的图的基本操作必须在此存储结构上实现
int visited[MAXSIZE]={0};
int Exist_Path_DFS(ALGraph G,int i,int j){
int p;
if(i==j)
return 1;
else{
visited[i]=1;
for (p=FirstNeighbor(G,i);p>=0;p=NextNeighbor(G,i,p)){
k = p.adjvex;
if(!visited[p] && Exist_Path_DFS(G,p,j))
return 1;
}
}
return 0;
}
int visited[MAXSI2E]={0};
int Exist_Path_BFS(ALGraph G,int i,int j){
InitQueue(Q);
EnQueue(Q,i);
while(!isEmpty(Q)){
DeQueue(Q,u);
visited[u]=1;
for(p=FirstNeighbor(G,i);p;p=NextNeighbor(G,i,p)){
k=p.adjvex;
if(k==j)
return 1;
if(!visited[k])
EnQueue(Q,k);
}
}
return 0;
}
6-5-假设图用邻接表表示,设计一个算法,输出从顶点 Vi 到顶点Vj 的所有简单路径。
void FindPath(AGraph *G,int u,int v,int path[],int d){
int w,i;
ArcNode *p;
d++;
path[d]=u;
visited[u]=1;
if(u==V)
print(path[]);
p=G->adjlist[u].firstarc;
while(p!=NULL){
w=p->adjvex;
if(visited[w]==0)
FindPath(G,w,V,path,d);
p = p->nextarc;
}
visited[u] = 0;
}
第七章-查找
7-1-写出折半查找的递归算法。初始调用时,low为1,high为 ST.length
typedef struct{
int *elem;
int length;
}SSTable;
int BinSearchRec(SSTable ST,int key,int low,int high){
if(low>high)
return 0;
mid=(low+high)/2;
if(key>ST.elem[mid])
Search(ST,key,mid+1,high);
else if(key<ST.elem[mid])
Search(ST,key,low,mid-1);
else
return mid;
}
7-2-线性表中各结点的检索概率不等时,可用如下策略提高顺序检索的效率:若找到指定的结点,则将该结点和其前驱结点(若存在)交换,使得经常被检索的结点尽量位于表的前端。试设计在顺序结构和链式结构的线性表上实现上述策略的顺序检索算法。
int SeqSrch(int R[],int k){
int i=0;
while((R[i].key!=k) &&(i<n))
i++;
if(i<n && i>0){
temp=R[i];
R[i]=R[i-1];
R[i-1]=temp;
return --i;
else
return -1;
}
第八章-排序
8-1-试重新编写考点精析中的快速排序的划分算法,使之每次选取的枢轴值都是随机地从当前子表中选择的。
int Partition2(int A[],int low,int high){
int rand_Index=low+rand() %(high-low+1);
Swap(A[rand Index],A[low]);
int pivot=A[low];
int i=low;
for(int j=low+1;j<=high;j++)
if(A[j]<pivot)
swap(A[++i],A[j]);
swap(A[i],A[low]);
return i;
}
8-2-试编写一个算法,使之能够在数组L[1…n]中找出第 k 小的元素(即从小到大排序后处于第k个位置的元素)
int kth_elem(int a[],int low,int high,ing k)
{
int pivot = a[low];
int low temp=low;
int high_temp=high;
while(low<high){
while(low<high && a[high]>=pivot)
--high;
a[low] =a[high];
while(low<high && a[low]<=pivot)
++low;
a[high]=a[low];
}
a[low]=pivot;
if(low==k)
return a[low];
else if(low>k)
return kth_elem(a,low_temp,low-1,k);
else
return kth_elem(a,low+1,high_temp,k-low);
}
8-3-已知由n(n>2)个正整数构成的集合A={ak l 0<=k<n},将其划分为两个不相交的子集A1和A2,元素个数分别是n1和n2,A1和A₂中的元素之和分别为S1和S₂。设计一个尽可能高效的划分算法,满足|n1-n2l最小且|S1-S2|最大。
int setPartition(int a[],int n){
int pivotkey,low=0,low0=0,high=n-1,high0=n-1,flag=1,k=n/2,i;
int s1=0,s2=0;
while(flag){
piovtkey = a[low];
while(low<high){
while(low<high && a[high]>=pivotkey)-high;
if(low!=high) a[low]=a[high];
while(low<high && a[low]<=pivotkey)
++low;
if(low!=high)
a[high]=a[low];
}
a[low]=pivotkey;
if(low==k-1)
flag=0;
else{
if(low<k-1){
low0 = ++low;
high = high0;
}
else{
high0 = --high;
low=low0;
}
}
}
for(i=0;i<k;i++) s1 += a[i];
for(i=k;i<n;i++) s2 += a[i];
return s2-s1;
}
8-4-荷兰国旗问题:设有一个仅由红、白、蓝三种颜色的条块组成的条块序列,请编写一个时间复杂度为O(n)的算法,使得这些条块按红、白、蓝的顺序排好,即排成荷兰国旗图案。
typedef enum(RED,WHITE,BLUE} color;
void Flag_Arrange(color a[],int n){
int i=0,j=0,k=n-1;
while(j<=k)
switch(a[j]){
case RED:Swap(a[i],a[j]);i++; j++; break;
case WHITE:j++;break;
case BLUE:Swap(a[j],a[k]); k--;
}
}
8-5-编写双向冒泡排序算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行。
void BubbleSort(int A,int n){
int low = 0,high = n-1;
bool flag = true;
while(low<high && flag){
flag=false;
for(i=low;i<high;i++)
if(a[i]>a[i+1]){
swap(a[i],a[i+1]);
flag=true;
}
high--;
for(i=high;i>low;i--)
if(a[i]<a[i-1]){
swap(a[i],a[i-1]);
flag=true;
}
low++;
}
8-6-已知线性表按顺序存储,且每个元素都是不相同的整数型元素,设计把所有奇数移动到所有偶数前边的算法(要求时间最少,辅助空间最少)
void move(int A[],int len){
int i=0,j=len-1;
while(i<j){
while(i<j && A[i]%2!=0) i++;
while(i<j && A[j]%2!=1) j--;
if(i<j){
Swap(A[i],A[j]);
i++;
j--;
}
}
}
8-7-编写一个算法,在基于单链表表示的待排序关键字序列上进行简单选择排序
void selectSort(LinkedList& L) {
LinkNode *h=L,*p,*q,*r,*s;
L=NULL;
while(h!=NULL){
p = s = h;
q = r = NULL;
while(p !=NULL){
if(p->data>s->data){
s = p;
r = q;
}
q = p;
p = p->1ink;
}
if(s==h)
h = h->1ink;
else
r->1ink = s->1ink;
s->1ink=L;
L=s;
}
}
8-8-试设计一个算法,判断一个数据序列是否构成一个小根堆。
bool IsMinHeap(int A[],int len){
if(len%2 == 0){
if(A[len/2]>A[len])
return false;
for(i=len/2-1; i>=1; i--)
if(A[i]>A[2*i] || A[i]>A[2*i+1])
return false;
else{
for(i=len/2; i>=1; i--)
if(A[i]>A[2*i] || A[i]>A[2*i+1])
return false;
}
return true;
}
8-9-设顺序表用数组A[]表示,表中元素存储在数组下标1~m+n的范围内,前m个元素递增有序,后n个元素递增有序,设计一个算法,使得整个顺序表有序。
void Insert_Sort(int A[],int m,int n){
int i,j;
for(i = m+1;i<=m+n;i++){
A[0]=A[i];
for(j=i-1;A[j]>A[0];j--)
A[j+1] = A[j];
A[j+1] = A[0];
}
}