【C语言实现】数据结构算法题及答案

数据结构算法题目集

改天有空再弄一个目录索引。

  1. 试设计算法,对带头结点的单链表实现就地逆置,即利用原单链表中的结点的存储单元,将链表逆置。
copy
typedef struct LNode { int data; struct LNode* next; }LNode,*LinkList; void inverse(LinkList&L) { p = L->next; L->next = NULL; while(p) { succ = p->next; //succ指向*p的后继 p->next = L->next; L->next = p; //*p插入在头结点之后 p = succ; } }

  1. 设计在顺序有序表中实现二分查找的算法。
copy
struct record { int key; int others; }; int bisearch(struct record r[],int k) { int low = 0,mid,high = n-1; while(low <= high) { mid = (low+high)/2; if(r[mid].key == k) return(mid+1); else if(r[mid].key > k) high = mid-1; else low = mid+1; } return 0; }

  1. 设计在单链表中删除值相同的多余结点的算法。
copy
typedef int datatype; typedef struct node { datatype data; struct node *next; }lklist; voidd elredundant(lklist*&head) { lklist *p,*q,*s; for(p = head;p != 0;p = p->next) { for(q = p->next,s = q; q != 0) if(q->data == p->data) { s->next = q->next; free(q); q = s->next; } else { s = q; q = q->next; } } }

  1. 设计一个求结点 x 在二叉树中的双亲结点算法。
copy
typedef struct node{ int data; struct node *lchild,*rchild; }bitree; bitree *q[20]; int r = 0,f = 0,flag = 0; void preorder(bitree *bt,char x) { if(bt != 0 && flag == 0) if(bt->data == x) { flag = 1; return; } else { r = (r+1) % 20; q[r] = bt; preorder(bt->lchild, x); preorder(bt->rchild, x); } } void parent(bitree *bt,char x) { int i; preorder(bt,x); for(i = f+1;i <= r; i++) if(q[i]->lchild->data == x || q[i]->rchild->data) break; if(flag == 0) printf("not found x\n"); else if(i <= r) printf("%c",bt->data); else printf("not parent"); }

  1. 设单链表中有仅三类字符的数据元素(大写字母、数字和其它字符),要求利用原单链表中结点空间设计出三个单链表的算法,使每个单链表只包含同类字符。
copy
typedef char datatype; typedef struct node { datatype data; struct node *next; }lklist; void split(lklist *head, lklist *&ha, lklist *&hb, lklist *&hc) { lklist *p; ha = 0, hb = 0, hc = 0; for(p = head; p != 0; p = head) { head = p->next; p->next = 0; if(p->data >= 'A' && p->data <= 'Z') { p->next = ha; ha = p; } else if(p->data >= '0' && p->data <= '9') { p->next = hb; hb = p; } else { p->next = hc; hc = p; } } }

  1. 设计在链式存储结构上交换二叉树中所有结点左右子树的算法。
copy
typedef struct node { int data; struct node *lchild,*rchild; }bitree; void swapbitree(bitree*bt) { bitree *p; if(bt == 0) return; swapbitree(bt->lchild); swapbitree(bt->rchild); p = bt->lchild; bt->lchild = bt->rchild; bt->rchild = p; }

  1. 在链式存储结构上建立一棵二叉排序树。
copy
#define n 10 typedef struct node { int key; struct node *lchild,*rchild; }bitree; void bstinsert(bitree*&bt,int key) { if(bt == 0) { bt = (bitree*)malloc(sizeof(bitree)); bt->key = key; bt->lchild = bt->rchild = 0; } else if(bt->key>key) bstinsert(bt->lchild,key); else bstinsert(bt->rchild,key); } void createbsttree(bitree*&bt) { int i; for(i = 1;i <= n;i++) bstinsert(bt,random(100)); }

  1. 设计判断两个二叉树是否相同的算法。
copy
typedef struct node { datatype data; struct node *lchild,*rchild; }bitree; int judgebitree(bitree *bt1,bitree *bt2) { if(bt1 == 0 && bt2 == 0) return 1; else if(bt1 == 0 || bt2 == 0 || bt1->data!=bt2->data) return 0; else return(judgebitree(bt1->lchild,bt2->lchild)*judgebitree(bt1->rchild,bt2->rchild)); }

  1. 设计两个有序单链表的合并排序算法。
copy
void mergelklist(lklist *ha,lklist *hb,lklist *&hc) { lklist *s = hc = 0; while(ha != 0 && hb != 0) if(ha->data < hb->data) { if(s == 0) hc = s = ha; else { s->next = ha; s = ha; } ha = ha->next; } else { if(s == 0) hc = s = hb; else { s->next = hb; s = hb; } hb = hb->next; } if(ha == 0) s->next = hb; else s->next = ha; }

  1. 设计在链式结构上实现简单选择排序算法。
copy
void simpleselectsorlklist(lklist *&head) { lklist *p,*q,*s; int min,t; if(head == 0 || head->next == 0) return; for(q = head;q != 0;q = q->next) { min = q->data; s = q; for(p = q->next; p != 0;p = p->next) if(min > p->data) { min = p->data; s = p; } if(s != q) { t = s->data; s->data = q->data; q->data = t; } } }

  1. 设计在顺序存储结构上实现求子串算法。
copy
void substring(char s[],long start,long count,char t[]) { long i,j,length = strlen(s); if(start<1 || start > length) printf("The copy position is wrong"); else if(start+count-1 > length) printf("Too characters to be copied"); else { for(i = start-1,j = 0;i < start+count-1;i++,j++) t[j] = s[i]; t[j] = '\0'; } }

  1. 设计求结点在二叉排序树中层次的算法。
copy
int lev=0; typedef struct node{ int key; struct node *lchild,*rchild; }bitree; void level(bitree *bt,int x) { if(bt != 0) { lev++; if (bt->key == x) return; else if(bt->key > x) level(bt->lchild, x); else level(bt->rchild, x); }

  1. 设计一个在链式存储结构上统计二叉树中;的算法。
copy
void countnode(bitree *bt,int &count) { if(bt != 0) { count++; countnode(bt->lchild, count); countnode(bt->rchild, count); } }

  1. 设计一个算法将无向图的邻接矩阵转为对应邻接表的算法。
copy
typedef struct { intvertex[m]; intedge[m][m]; }gadjmatrix; typedef struct node1{ int info; int adjvertex; struct node1 *nextarc; }glinklistnode; typedef struct node2 { int vertexinfo; glinklistnode *firstarc; }glinkheadnode; void adjmatrixtoadjlist(gadjmatrix g1[],glinkheadnode g2[]) { inti,j; glinklistnode *p; for(i = 0;i <= n-1;i++) g2[i].firstarc = 0; for(i = 0;i <= n-1;i++) for(j = 0;j <= n-1;j++) if(g1.edge[i][j] == 1) { p = (glinklistnode*)malloc(sizeof(glinklistnode)); p->adjvertex = j; p->nextarc = g[i].firstarc; g[i].firstarc = p; p = (glinklistnode*)malloc(sizeof(glinklistnode)); p->adjvertex = i; p->nextarc = g[j].firstarc; g[j].firstarc = p; } }

  1. 设计计算二叉树中所有结点值之和的算法。
copy
void sum(bitree *bt,int &s) { if(bt != 0) { s = s + bt->data; sum(bt->lchild,s); sum(bt->rchild,s); } }

  1. 设计将所有奇数移到所有偶数之前的算法。
copy
void quickpass(int r[],ints,int t) { int i = s,j = t,x = r[s]; while(i<j) { while(i<j && r[j]%2 == 0) j = j-1; if(i<j) { r[i] = r[j]; i = i+1; } while(i<j && r[i]%2 == 1) i = i+1; if(i<j) { r[j] = r[i]; j = j-1; } } r[i] = x; }

  1. 设计判断单链表中元素是否是递增的算法。
copy
int isriselk(lklist *head) { if(head == 0||head->next == 0) return 1; else for(q = head,p = head->next; p! = 0; q = p, p = p->next) if(q->data > p->data) return 0; return 1; }

  1. 设计在链式存储结构上合并排序的算法。
copy
void mergeLinkList(LinkList *ha,LinkList *hb,LinkList *&hc) { LinkList *s = hc = 0; while(ha! = 0 && hb! = 0) { if(ha->data < hb->data) { if(s == 0) hc = s = ha; else { s->next = ha; s = ha; }; ha = ha->next; } else { if(s == 0) hc = s = hb; else { s->next = hb; s = hb; }; hb = hb->next; } if(ha == 0) s->next = hb; else s->next = ha; } }
  1. 设计在二叉排序树上查找结点 X 的算法。
copy
BiTree *bstsearch1(BiTree *t,int key) { BiTree *p = t; while(p! = 0) { if (p->key == key) return(p); else if (p->key > key) p = p->lchild; else p = p->rchild; } return 0; }

  1. 设关键字序列 ( K1、K2、...、Kn-1 ) 是堆,设计算法将关键字序列 ( K1、K2、...、Kn-1、X ) 调整为堆。
copy
void adjustheap(int r[],int n) { intj = n,i = j/2,temp = r[j-1]; while(i> = 1) if(temp> = r[i-1]) break; else { r[j-1] = r[i-1]; j = i; i = i/2; } r[j-1] = temp; }

  1. 设计一个算法,求一个带头结点的单链表中的结点个数。
copy
int CountNodes(LinkList&L) { int count=0; LinkList p; p = L->next; while(p){ count++; p = p->next; } return count; }

  1. .已知两个非空的带有头结点的单链表 La 和 Lb,且 L 和 La和 Lb的元素按值非递减排列(即元素按值递增有序),试设计算法将该两个有序链表合并为一个有序链表。
copy
void MergeList(LinkList &LA,LinkList &LA,LinkList &LC) { pa = LA->next; pb = LB->next; LC = pC = LA; while(pa&&pb){ if(pa->data< = pb->data)( pc->next = pa;pc = pa;pa = pa->next; else{pc->next = pb;pc = pb;pb = pb->next;} pc->next = pa ? pa:pb; free(LB); }

  1. 设计判断二叉树是否为二叉排序树的算法。
copy
int minnum = -32768,flag = 1; typedef struct node { int key; struct node *lchild,*rchild; }bitree; void inorder(bitree*bt) { if (bt != 0) { inorder(bt->lchild); if(minnum > bt->key) flag = 0; minnum = bt->key; inorder(bt->rchild); } }

  1. 在链式存储结构上设计直接插入排序算法。
copy
void straightinsertsort(lklist *&head) { lklist *s,*p,*q; int t; if(head == 0||head->next == 0) return; else for(q = head, p = head->next; p! = 0; p = q->next) { for(s = head; s != q->next; s = s->next) if(s->data > p->data) break; if(s == q->next) q = p; else { q->next = p->next; p->next = s->next; s->next = p; t = p->data; p->data = s->data; s->data = t; } } }

  1. 设有一组初始记录关键字序列 ( K1、K2、...、Kn ),要求设计一个算法能够在 O(n) 的时间复杂度内将线性表划分成两部分,其中左半部分的每个关键字均小于 Ki,右半部分的每
    个关键字均大于等于 Ki
copy
void quickpass(int r[],int s,int t) { int i = s, j = t, x = r[s]; while(i<j) { while(i<j && r[j]>x) j = j-1; if(i<j) { r[i] = r[j]; i = i+1; } while(i<j && r[i]<x) i = i+1; if(i<j) { r[j] = r[i]; j = j-1; } } r[i] = x; }

  1. 设有两个集合 A和集合 B,要求设计生成集合 C=A∩B 的算法,其中集合 A、B和 C 用
    链式存储结构表示。
copy
typedef struct node { int data; struct node *next; }lklist; void intersection(lklist *ha,lklist *hb,lklist *&hc) { lklist *p,*q,*t; for(p = ha, hc = 0; p != 0;p = p->next) { for(q = hb; q!=0; q = q->next) if(q->data == p->data) break; if(q != 0) { t = (lklist*)malloc(sizeof(lklist)); t->data = p->data; t->next = hc; hc = t; } } }

  1. 假设二叉树采用二叉链存储结构存储,设计一个算法,求出根结点到给定某结点之间的路径。
copy
typedef struct BiTNode{ int data; // 数据域 struct BiTNode *lchild,*rchild; // 左、右;指针 }BTNode,*BiTree; #define MaxSize 100 int AncestoPath(BTNode *b, BTNode *s) { BTNode* st[MaxSize]; BTNode *p; int i,flag,top = -1; do{ while(b != NULL){ st[++top]=b; b = b->lchild; } p = NULL; //p 指向当前结点的前一个已访问结点 flag = 1; // 设置 b 的访问标记为已访问 while(top!=-1 && flag){ b = st[top]; // 取出栈顶元素 if(b->rchild == p){ // 右子树不存在或已被访问,访问之 if(b == s){ // 找到目标结点,输出路径 for(i = 0; i <= top; ++i) printf("%c", st[i]->data); return 1; } else { top--; p=b; //p 指向刚才访问的结点 } } else { b=b->rchild; //b 指向右子树 flag=0; //设置未被访问标记 } } }while(top != -1); //栈不空时循环 return 0; //其他情况返回 0 }

  1. 将一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。输入一个已排好序数组的一个旋转,求该旋转数组的最小元素。如,数组 {3, 4, 5, 1, 2} 为有序数组{1, 2, 3, 4, 5}的一个旋转数组,该数组的最小值为1。
copy
int Min(int *numbers,int length) { if(numbers == 0 || length <= 0) return 0; int index1 = 0; // 第一个指针 int index2 = length-1; // 第二个指针 int indexMid = index1; // 中间指针 while(numbers[index1]> = numbers[index2]) { if(index2-index1 == 1) { indexMid = index2; break; } indexMid = (index1+index2)/2; if(numbers[indexMid] >= numbers[index1]) //在右区间 index1 = indexMid; else if(numbers[indexMid] <= numbers[index2]) //在左区间 index2 = indexMid; } return numbers[indexMid]; }

  1. 假设二叉树采用二叉链表存储结构存储,设计一个算法,求先序遍历序列中第k (1 ≤ k ≤ 二叉树中结点个数)个结点的值。
copy
typedef struct BiTNode{ int data; // 数据域 struct BiTNode *lchild,*rchild; // 左、右;指针 }BTNode,*BiTree; int n = 1; //递归实现 int PreNode(BTNode *b,int k) { int ch; if(b == NULL) return '#'; if(n == k) return b->data; ++n; ch = PreNode(b->lchild,k); if(ch ! = '#') return ch; ch = PreNode(b->rchild,k); return ch; } //非递归实现 #define MaxSize 100 int n = 1; int PreNode(BTNode *b,int k) { BTNode *st[MaxSize],*p; if(b != NULL) { st[++top] = b; while(top>-1) { p = st[top--]; ++n; if(n == k) return p->data; if(p->rchild) st[++top] = p->rchild; // 右子树进栈 if(p->lchild) st[++top] = p->lchild; // 左子树进栈 } } return ''; }

  1. 在数组中,某个数字减去它右边的数字得到一个数对之差。求所有数对之差的最大值。例如,在数组 {2, 4, 1, 16, 7, 5, 11, 9} 中,数对之差的最大值是 11,是 16 减去 5 的结果。
copy
//解法一 int MaxDiff_Solution1(int numbers[], unsigned length) { if(numbers == NULL || length<2) return 0; int max,min; return MaxDiffCore(numbers,numbers+length-1, &max, &min); } int MaxDiffCore(int* start,int* end,int* max,int* min) { if(end == start) { *max = *min = *start; return 0; } int* middle = start+(end-start)/2; int maxLeft, minLeft; int leftDiff = MaxDiffCore(start,middle,&maxLeft,&minLeft); int maxRight, minRight; int rightDiff = MaxDiffCore(middle+1,end,&maxRight,&minRight); int crossDiff = maxLeft-minRight; *max = (maxLeft>maxRight)? maxLeft:maxRight; *min = (minLeft<minRight)? minLeft:minRight; int maxDiff = (leftDiff>rightDiff)? leftDiff:rightDiff; maxDiff = (maxDiff>crossDiff)? maxDiff:crossDiff; return maxDiff; } //解法二 int MaxDiff_Solution2(int numbers[],unsigned length) { if(numbers == NULL||length<2) return 0; int max = numbers[0]; // 第i个数之前的最大值 int maxDiff = max-numbers[1]; // maxDiff 表 示diff[i-1] for(int i = 2; i<length; ++i) { if(numbers[i-1] > max) // 第i 个数和之前的最大值比较 max = numbers[i-1]; int currentDiff = max-numbers[i]; //currentDiff 表示diff[i] if(currentDiff > maxDiff) maxDiff = currentDiff; } return maxDiff; }

  1. 假设二叉树采用二叉链表存储结构,设计一个算法求其指定的某一层 k(k>1)的叶子结点个数。
copy
//解法一 typedef struct BiTNode{ ElemType data; // 数据域 struct BiTNode *lchild,*rchild; // 左、右;指针 }BTNode,*BiTree; #define MaxSize 100 // 设置队列的最大容量 int LeafKLevel(BTNode *root,int k) { BTNode* q[MaxSize]; // 声明队列, end1 为头指针, end2为尾指针 int end1, end2, sum=0; // 队列最多容纳 MaxSize-1 个元素 end1 = end2 = 0; // 头指针指向队头元素,尾指针指向队尾的后一个元素 int deep = 0; // 初始化深度 BTNode *lastNode; // lastNode 用来记录当前层的最后一个结点 BTNode *newlastNode; // newlastNode 用来记录下一层的最后一个结点 lastNode = root; //lastNode 初始化为根节点 newlastNode = NULL; //newlastNode 初始化为空 q[end2++] = root; // 根节点入队 while(end1 != end2) { // 层次遍历,若队列不空则循环 BTNode *t = q[end1++]; // 拿出队列中的头一个元素 if(k==deep) { // 找到特定层,统计叶子结点个数 while(end1 != end2) { t = q[end1++]; if(t->lchild == NULL && t->rchild == NULL) ++sum; } break; } else { // 没到特定层,层次遍历 if(t->lchild != NULL) { // 若非叶子结点把左结点入队 q[end2++] = t->lchild; newlastNode = t->lchild; } // 并设下一层的最后一个结点为该结点的左结点 if(t->rchild != NULL) { // 处理叶节点 q[end2++] = t->rchild; newlastNode = t->rchild; } if(t == lastNode) { // 若该结点为本层最后一个结点,更新lastNode lastNode = newlastNode; deep += 1; // 层数加 1 } } } return sum; // 返回叶子结点个数 } //解法二 int n; int LeafKLevel(BiTree root, int k) { n=0; PreOrder(root, 0, k); return 0; } int PreOrder(BiTree root, int deep, int k) { if(deep<k) { if(root->lchild != NULL) //若左子树不空,对左子树递归遍历 PreOrder(root->lchild, deep+1); if(root->rchild != NULL) //若右子树不空,对右子树递归遍历 PreOrder(root->rchild, deep+1); } else if(deep == k && root->lchild == NULL && root->rchild == NULL) ++n; }

  1. 设有 n 个不全为负的整型元素存储在一维数组 A[n]中,它包含很多连续的子数组,例如数组 A={1,-2,3,10,-4,7,2,-5 },请设计一个时间上尽可能高效的算法,求出数组 A 的子数组之和的最大值 (例如数组 A 的最大的子数组为 { 3,10,-4,7,2 },因此输出为该子数组的和 18)。
copy
int MaxSum(int n,int *a){ int sum=0,b=0; for(int i=1;i<=n;i++){ if(b>0) b+=a[i]; else b=a[i]; if(b>sum) sum=b; } return sum; }

  1. 编写算法判断该二叉树是否是平衡二叉树,即二叉树中任意结点的左右子树的深度相差不超过 1。
copy
void Judge_AVL(BiTree bt,int &balance,int &h) { int bl,br,hl,hr; // 左、右子树的平衡标记和高度 if(bt == NULL) { // 空树,高度为 0 h = 0; balance = 1; } else if(p->lchild == NULL && p->rchild == NULL) { // 仅有根结点,则高度为 1 h = 1; balance = 1; } else { Judge_AVL(bt->lchild,bl,hl); // 递归判断左子树 Judge_AVL(bt->rchild,br,hr); // 递归判断右子树 h = (hl>hr ? hl : hr)+1; if(abs(hl,hr) < 2) // 若高度绝对值小于 2 ,则看左、右子树是否都平衡 balance = bl & br; // &为逻辑与,即左、右子树都平衡时,二叉树平衡 else balance = 0; } }

  1. 单链表有环,是指单链表的最后一个结点的指针指向了链表中的某个结点(通常单链表的最后一个结点的指针域是为空的)。试编写算法判断单链表是否存在环。
copy
bool IsExitsLoop(list *head) { list *slow = head, *fast = head; // 定义两个指针 while(fast && fast->next) // 都不空 { slow = slow->next; fast = fast->next->next; if(slow == fast) // 相遇,存在环 break; } return !(fast == NULL || fast->next == NULL); }

  1. 已知线性表(a 1 , a 2 , a 3 ,…,a n)存放在一维数组 A 中。试设计一个在时间和空
    间两方面都尽可能高效的算法,将所有奇数号元素移到所有偶数号元素前,并且不得
    改变奇数号(或偶数号)元素之间的相对顺序。
copy
void Bubble_Swap(int A[],int n) { int i = n,v = 1; // i 为工作指针,初始假设 n 为奇数, v 为“块”的大小 int temp; // 辅助变量 if( n%2 == 0) i = n-1; // 若 n 为偶数,则令 i 为 n-1 while(i>1) { // 假设数组从 1 开始存放。当 i = 1 时,气泡浮出水面 temp = A[i-1]; // 将“块”前的偶数号元素暂存 for(int j = 0; j<v; j++) // 将大小为 v 的“块”整体向前平移 A[i-1+j] = A[i+j]; // 从前往后依次向前平移 A[i+v-1] = temp; // 暂存的奇数号元素复制到平移后空出的位置 i = i-2; v++; // 指针向前,块大小增 1 } }

  1. 已知长度为 n(n>1)的单链表,表头指针为 L,判断该单链表是否中心对称。
copy
typedef struct LNode{ char data; // 结点数据 struct LNode *next; // 结点链接指针 } *LinkList; int Str_Sym(LinkList L,int n) { Stack s; initstack(s); // 初始化栈 LNode *q,*p = L->next; //q 指向出栈元素,p 工作指针 for(int i = 1;i <= n/2;i++) { // 前一半结点入栈 push(p); p = p->next; } if( n%2 == 1) p = p->next; // 若 n 为奇数,需要特殊处理 while(p != null){ // 后一半表依次和前一半表比较 q = pop(s); // 出栈一个结点 if(q->data == p->data) p = p->next; // 相等则继续比较下一个结点 else break; // 不等则跳出循环 } if(empty(s)) return 1; // 栈空,则说明对称 else return 0; // 否则不对称 }


  1. 现要求设计一个时间复杂度尽可能高效的算法,对于链表中 data 的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。
copy
typedef struct node { int data; struct node *link; } NODE; Typedef NODE *PNODE; void func (PNODE h,int n) { PNODE p = h,r; int *q,m; q = (int *)malloc(sizeof(int)*(n+1)); //申请 n+1个位置的辅助空间 for (int i = 0;i<n+1;i++) //数组元素初值置 0 *(q+i) = 0; while(p->link! = NULL) { m = p->link->data > 0 ? p->link->data : -p->link->data; if( *(q+m) == 0) //判断该结点的 data是否已出现过 { *(q+m) = 1; //首次出现 p = p->link; //保留 } else //重复出现 { r = p->link; //删除 p->link = r->link free(r); } } free(q); }

  1. 设 root 为指向 T 的根结点的指针,请设计求 T 的 WPL 的算法。
copy
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; //定义一个 static变量存储 wpl if(root->lchild == NULL && root->lchild == NULL) //若为叶子结点,累积 wpl wpl += deep * root->weight; if(root->lchild != NULL) //若左子树不空,对左子树递归遍历 wpl_PreOrder(root->lchild, deep+1); if(root->rchild != NULL) //若右子树不空,对右子树递归遍历 wpl_PreOrder(root->rchild, deep+1); return wpl; }

  1. 已知一个整数序列 A=(A0 , A1 , …, An+1 ),其中 0 ≤ Ai <n(0 ≤ i<n)。若存在 Ap1 = Ap2 =…= Apm = x 且 m> n/2 (0 ≤ pk <n,1 ≤ k ≤m),则称 x 为 A 的主元素。例如 A=(0, 5, 5, 3, 5, 7, 5, 5),则 5 为主元素;又如 A=(0, 5, 5, 3, 5, 1, 5, 7),则 A 中没有主元素。假设 A 中的 n 个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出 A 的主元素。若存在主元素,则输出该元素;否则输出-1。
copy
int Majority(int A[],int n) { int i,c,count = 1; //c用来保存候选主元素,count用来计数 c = A[0]; //设置 A[0]为候选主元素 for(i = 1; i<n; i++) //查找候选主元素 if(A[i] == c) count++; //对 A中的候选主元素计数 else if(count>0) //处理不是候选主元素的情况 count--; else //更换候选主元素,重新计数 { c = A[i]; count = 1; } if(count>0) for(i = count = 0; i<n; i++) //统计候选主元素的实际出现次数 if(A[i] == c) count++; if(count>n/2) return c; //确认候选主元素 else return -1; //不存在主元素 }

  1. 设 str1 和 str2 分别指向两个单词所在单链表的头结点,链表结点结构为 ,请设计一个时间上尽可能高效的算法,找出由 str1 和 str2 所指向两个链表共同后缀的起始位置。
copy
LinkNode *Find_1st_Common(LinkList str1,LinkList str2) { int len1 = Length(str1),len2 = Length(str2); LinkNode *p,*q; for(p = str1;len1>len2;len1--) //使 p指向的链表与 q指向的链表等长 p = p->next; for(q = str2;len1<len2;len2--) //使 q指向的链表与 p指向的链表等长 q = q->next; while(p->next != NULL&&p->next != q->next) { //查找共同后缀起始点 p = p->next; //两个指针同步向后移动 q = q->next; } return p->next; //返回共同后缀的起始点 }

  1. 一个长度为 L(L≥1)的升序序列 S,处在第 L/2 个位置的数称为 S 的中位数。例如,若序列 S1=(11,13,15,17,19),则 S1 的中位数是 15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若 S2=(2,4,6,8,20),则 S1 和 S2 的中位数是 11。现在有两个等长升序序列 A 和 B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列 A 和 B 的中位数。
copy
int M_Search(int A[],int B[],int n) { int s1 = 0,d1 = n-1,m1,s2 = 1,d2 = n-1,m2; //分别表示序列 A和 B的首位数、末位数和中位数 while(s1 != d1||s2 != d2) { m1 = (s1+d1)/2; m2 = (s2+d2)/2; if(A[m1] == B[m2]) return A[m1]; //满足条件 1) if(A[m1] < B[m2]) { //满足条件 2) if((s1+d1)%2 == 0) { //若元素个数为奇数 s1 = m1; //舍弃 A中间点以前的部分,且保留中间点 d2 = m2; //舍弃 B中间点以后的部分,且保留中间点 } else { //元素个数为偶数 s1 = m1+1; //舍弃 A中间点及中间点以前部分 d2 = m2; //舍弃 B中间点以后部分且保留中间点 } } else { //满足条件 3) if( (s1+d1)%2 == 0) { //若元素个数为奇数 d1 = m1; //舍弃 A中间点以后的部分,且保留中间点 s2 = m2; //舍弃 B中间点以前的部分,且保留中间点 } else { //元素个数为偶数 d1 = m1+1; //舍弃 A中间点以后部分,且保留中间点 s2 = m2; //舍弃 B中间点及中间点以前部分 } } } return A[s1]<B[s2] ? A[s1]:B[s2]; }

  1. 设将 n(n>1)个整数存放到一维数组 R 中。试设计一个在时间和空间两方面都尽可能高效的算法。将 R 中保存的序列循环左移 p(0<p<n)个位置。
copy
void Reverse(int R[],int from,int to) { int i,temp; for(i = 0; i< (to-from+1)/2; i++) { temp = R[from+i]; R[from+i] = R[to-i]; R[to-i] = temp; } } void Converse(int R[],int n,int p) { Reverse(R,0,p-1); Reverse(R,p,n-1); Reverse(R,0,n-1); }

  1. 查找链表中倒数第 k 个位置上的结点(k 为正整数)。若查找成功,算法输出该结点的 data 域的值,并返回 1;否则,只返回 0。
copy
typedef int ElemType; //链表数据的类型定义 typedef struct LNode { //链表结点的结构定义 ElemType data; //结点数据 struct Lnode *link; //结点链接指针 } *LinkList; int Search_k(LinkList list,int k) { //查找链表 list倒数第 k个结点,并输出该结点 data域的值 LinkList p = list->link,q = list->link; //指针 p、q指示第一个结点 int count = 0; while(p != NULL) { //遍历链表直到最后一个结点 if(count<k) count++; //计数,若 count<k只移动 p else q = q->link;p = p->link; //之后让 p、q同步移动 } if(count<k) return 0; //查找失败返回 0 else { //否则打印并返回 1 printf("%d",q->data); return 1; } }

  1. 已知二叉树用二叉链表方式存在,编写算法,统计二叉树中的叶子结点数目并输出所有的叶子结点。
copy

  1. 已知无向图采用邻接表结构存储,要求按深度优先搜索策略统计连通子图的个数,并输出所有连通子图的生成树。(生成树中的边用 vi , vj )格式输出)
copy

  1. 已知树,采用;—兄弟表示法存储,编写算法,按(双亲、;)格式输出树中的边。
copy

  1. 已知二叉树采用二叉链表方式存放。请统计二叉树中度为 1 的结点数目,输出二叉树中所有的叶子结点。
copy

  1. 已知树采用;—兄弟的二叉链表存储,编写算法,按层次输出树中所有结点。
copy

  1. 键盘输入 N 个值,编写算法要求按照输入顺序依次建立链表中各个结点。
copy

  1. 已知二叉树采用二叉链表存放,要求编写算法不用递归也不用栈,返回二叉树T的后序序列中的第一个结点的指针。
copy

  1. 编写算法,为依次输入的 n 个元素构造哈希表,H(x) 为哈希函数,以线性探测再散列解决冲突。
copy

  1. 已知无向图采用邻接表结构存储,要求按广度优先搜索策略统计连通子图的个数,并输出所有连通子图的生成树。(生成树中的边用 vi , vj )格式输出)
copy

  1. 键盘输入一组非零的整数序列,最后输入 0 为结束标志,要求根据输入建立一棵二叉排序树算法,采用二叉链表存放。
copy

  1. 给出按由大到小顺序输出此二叉排序树中结点值的算法。
copy

  1. 已知二叉树采用二叉链表结构存放,要求统计二叉树中度为 1 结点个数和度为 2 的结点个数。
copy

  1. 建立一棵二叉树,要求以二叉链表存储结构存储。
copy

  1. 已知有N个结点的无向图,采用邻接表结构存储,要求由根开始逐层输出连通子图中所有生成树中的各条边,边输出格式为 ( Ki ,Kj ) 。
copy

  1. 键盘输入 n 个有序值建立线性表,按折半查找策略实习查找给定值为 key 的元素。
copy

  1. 编写二分查找的递归算法。
copy

  1. 编写算法,对一棵以;—兄弟链表表示的树统计其叶子结点的个数。
copy

  1. 已知 A=(a1, a2, …, am),B=(b1, b2, …, bn)均为顺序表,试编写一个比较 A¸B 大小的算法。
copy
int compare(SqList La, SqList Lb) { i = 0; while (i<La.Length && i<Lb.Length) { if (La.elem[i] == Lb.elem[i]) i++; else if (La.elem[i]<Lb.elem[i]) return -1; else return 1; } if ( i>La.length && i>Lb.Length) return 0; else if (i>Lb.Length) return 1; else return -1; }

  1. 删除有序表中所有其值大于 mink 且小于 maxk 的数据元素。
copy
void delete(LinkList &L, int mink, int maxk) { p = L->next; while (p && p->data <= mink) { pre = p; p = p->next; } //查找第一个值>mink 的结点 if (p) { while (p && p->data<maxk) p = p->next; //查找第一个值≥maxk 的结点 q = pre->next; pre->next = p; //修改指针 while (q != p) { s = q->next; delete q; q = s; } // 释放结点空间 } }

  1. 逆置线性链表
copy
void inverse(LinkList &L) { // 逆置带头结点的单链表 L p = L->next; L->next = NULL; while(p) { succ = p->next; // succ 指向*p 的后继 p->next = L->next; L->next = p; // *p 插入在头结点之后 p = succ; } }

  1. 已知数组 A[1..n]的元素类型为整型 int,设计一个时间和空间上尽可能高效的算
    法,将其调整为左右两部分,左边所有元素为奇数,右边所有元素为偶数。
copy
void Adjust(int A[]) { //调整数组 A,使得 A 的左边为奇数,右边为偶数 int i = 1,j = n,temp; while(i != j) { while(A[i]%2 != 0) i++; //A[i]为奇数时,i 增 1 while(A[j]%2 == 0) j++; //A[j]为偶数时,j 减 1 if (i<j) //A[i]为偶数、A[j]为奇数时,交换 { temp=A[i]; A[i]=A[j]; A[j]=temp; } } }

  1. 括号匹配的检验
copy
void match(char *exp) { initStack(s); char c; int i = 0, b = 1; while(exp[i] != '\0' && b == 1) { if (exp[i] == '(') push(S,exp[i]); else if (exp[i] == ')') { c = Pop(S); if (c != '(') b = 0; } i++; } return (b&&StackEmpty(S)); }

  1. 识别读入的一个字符序列是否为反对称的字符序列。
copy
int symmetry(char Ch[] ) { //若Ch[] 为反对称字符序列,则返回1,否则返回0。 p = Ch; InitStack(S); while (*p!='&') { Push(S,*p); p++; } state = 1; p++; // 滤去字符‘&’ while (*p!='@' && state ) { if (NOT StackEmpty(S)&&GetTop(S)==*p ) { Pop(S,e); p++; } else state = 0; } return(StackEmpty(S) && state ) }

  1. 判别读入的字符序列是否为“回文”。
copy
Status ex() { // 若从终端依次输入的字符序列是“回文”, // 则返回 TRUE,否则返回 FALSE InitStack(S); InitQueue(Q); scanf(ch); while(ch!=@) { Push(S, ch); EnQueue(Q, ch); scanf(ch); } state=TRUE; while(!StackEmpty && state) { if(GetTop(S)==GetHead(Q)) { Pop(S); DeQueue(Q); } else state=FALSE; } return state; }

  1. 中序遍历非递归算法
copy
void NRInOrder(BiTree bt) { BiTree Stack[MAX_TREE_SIZE],p; int top = 0; p = bt; if (bt == NULL) return; while(!(p == NULL && top == 0)) { while(p != NULL) { if(top < MAX_TREE_SIZE-1) //将当前指针 p 压栈 Stack[top++] = p; else { printf("栈溢出"); return; } p = p->lchild; //指针指向 p 的左;结点 } if (top <= 0) return; //栈空时结束 else { p = Stack[--top]; //从栈中弹出栈顶元素 Visit(p->data); //访问结点的数据域 p = p->rchild; //指针指向 p 的右;结点 } } }

  1. 先序非递归算法
copy
void PreOrder1(BiTree b) { BiTree St[MAX_TREE_SIZE],p; int top = -1; if (b != NULL) { St[++top] = b; //根结点进栈 while (top>-1) { //栈不空时循环 p = St[top--]; //出栈并访问该结点 Visit(p->data); if (p->rchild != NULL) //右;结点进栈 St[++top] = p->rchild; if (p->lchild != NULL) //左;结点进栈 St[++top] = p->lchild; } } }

  1. 后序遍历非递归算法
copy
void PostOrder1(BiTree b) { BiTree St[MAX_TREE_SIZE],p; int flag,top = -1; if (b != NULL) { do{ while(b != NULL) { //扫描*b 的左结点并进栈 St[++top] = b; b = b->lchild; } p = NULL; // p 指向栈顶结点的前一个已访问的结点 flag = 1; // 设置 b 的已访问标记为已访问过 while(top != -1 &&flag) { b = St[top]; //取出当前的栈顶元素 if (b->rchild == p) { //右;不存在或右;已被访问,则访问*b Visit(b->data); //访问*b 结点 top--; p = b; //p 指向被访问的结点 } else { b = b->rchild; //b 指向右;结点 flag = 0; //设置未被访问的标记 } } }while(top! = -1); } }

  1. 查询二叉树中某个结点
copy
Status Preorder (BiTree T, ElemType x, BiTree &p) { // 若二叉树中存在和 x 相同的元素, //则 p 指向该结点并返回 OK,否则返回 FALSE if(T) { if(T->data == x) { p = T; return OK; } else { if(Preorder(T->lchild, x, p) return OK; else return(Preorder(T->rchild, x, p)) ; } }//if else return FALSE; }

  1. 求二叉树的深度
copy
int Depth (BiTree T ) { // 返回二叉树的深度 if ( !T ) depthval = 0; else { depthLeft = Depth( T->lchild ); depthRight= Depth( T->rchild ); depthval = 1+ (depthLeft>depthRight ? depthLeft:depthRight); } return depthval; }

  1. 复制二叉树
copy
BiTree GetTreeNode(TElemType item,BiTNode *lptr , BiTNode *rptr) { if (!(T = new BiTNode)) exit(1); T-> data = item; T-> lchild = lptr; T-> rchild = rptr; return T; } BiTree CopyTree(BiTNode *T) { if (!T ) return NULL; if (T->lchild ) newlptr = CopyTree(T->lchild); //复制左子树 else newlptr = NULL; if (T->rchild ) newrptr = CopyTree(T->rchild); //复制右子树 else newrptr = NULL; newT = GetTreeNode(T->data, newlptr, newrptr); return newT; } // CopyTree

  1. 按给定的表达式建相应二叉树
copy
typedef struct node { ElemType data; float val; char optr; //只取‘+’, ‘-’, ‘*’,‘/’ struct node *lchild,*rchild; }BiNode,*BiTree; float PostEval(BiTree bt) { float lv,rv; if(bt! = null) { lv = PostEval(bt->lchild); // 求左子树表示的子表达式的值 rv = PostEval(bt->rchild); // 求右子树表示的子表达式的值 switch(bt->optr) { case '+': value = lv+rv; break; case '-': value = lv-rv; break; case '*': value = lv*rv; break; case '/': value = lv/rv; } } return(value); }

  1. 按层次遍历二叉树
copy
void LevelOrder(BiTree b) { BiTree Queue[MAX_TREE_SIZE]; int front,rear; if (b == NULL) return; front = -1; rear = 0; Queue[rear] = b; while(front != rear) { Visit(Queue[++front]->data); //访问队首结点数据域 if (Queue[front]->lchild != NULL) Queue[++rear] = Queue[front]->lchild; if (Queue[front]->rchild != NULL) Queue[++rear] = Queue[front]->rchild; } }

  1. 求森林的深度
copy
typedef struct CSNode{ int data; struct CSNode *firstchild, *nextsibling; }CSNode, *CSTree; int Depth(CSTree T) { if (T==NULL) return 0; else { d1 = Depth(T->firstchild); d2 = Depth(T->nextsibling); return Max(d1+1,d2); } }

  1. 假设二叉树采用二叉链表存储结构存储,设计一个算法,利用结点的右孩子指针 rchild 将一棵二叉树的叶子结点按从左往右的顺序串成一个单链表。
copy
void link(BiTree bt, BiTNode *head, BiTNode *tail) { //初始调用时 head = NULL if (bt! = NULL) { if (bt->lchild == NULL && bt->rchild == NULL) if (head == NULL) { //第一个叶子结点 head = bt; tail = head; } else { tail->rchild = bt; tail = bt; } if (bt->lchild! = NULL) link(bt->lchild,head,tail); if (bt->rchild! = NULL) link(bt->rchild,head,tail); } }

  1. 编写递归算法,求二叉树中以元素值为 x 的结点为根的子树的深度。
copy
int Get_Sub_Depth(Bitree T,int x) { if(T->data == x) { printf("%d\n",Get_Depth(T)); //找到值为 x 的结点,求其深度 exit 1; } else { if(T->lchild) //在左子树中继续寻找 Get_Sub_Depth(T->lchild,x); if(T->rchild) //在右子树中继续寻找 Get_Sub_Depth(T->rchild,x); } } int Get_Depth(Bitree T) { //求子树深度的递归算法 if(!T) return 0; else { m = Get_Depth(T->lchild); n = Get_Depth(T->rchild); return (m>n ?m :n)+1; } }

  1. 设树 T 采用孩子兄弟链表存储结构,设计算法求树 T 的叶子数目。
copy
void LeafCount_CSTree(CSTree T) { if(!T->FirstChild) return 1; //叶子结点 else { count=0; for(p=T->FirstChild;p;p->NextSibling) count += LeafCount_CSTree(p); return count; //各子树的叶子数之和 } }

  1. 编写算法求以孩子—兄弟表示法存储的森林的叶子结点数。
copy
typedef struct node { ElemType data; //数据域 struct node *fch, *nsib; //孩子与兄弟域 }*Tree; int Leaves (Tree t) { if(t = null) return 0; else if(t->fch == null) //若结点无孩子,则该结点必是叶子 return( 1 + Leaves(t->nsib)); else return ( Leaves(t->fch) + Leaves(t->nsib) ); }

  1. 试编写求无向图 G 的连通分量的算法。要求输出每一连通分量的顶点值。
copy
void DFS() { visited[v]=1; printf("%3d",v); //输出连通分量的顶点 p=g[v].firstarc; while (p!=NULL) { if(visited[p->adjvex==0]) DFS(p->adjvex); p=p->next; } } void Count( ) { //求图中连通分量的个数 int k=0 ; static AdjList g ; //设无向图 g 有 n 个结点 for (i=1;i<=n;i++ ) if (visited[i]= =0) { printf ("\n 第%d 个连通分量:\n",++k); DFS(i); } }

  1. 设二叉排序树已经以二叉链表的形式存储在内存中,使用递归方法,求各结点的平衡因子并输出。
copy
typedef struct BiTNode { int bf; //平衡因子 int data; struct BiTNode *lchild;*rchild; //左、右孩子指针 }BiTNode,*BiTree; int Computerbf(BiTree bt) { int hl,hr; if (bt = = NULL) return 0; //空树无平衡因子 if (bt->lchild = = NULL&& bt->rchild = = NULL) { bt->bf = 0; //无左、右孩子的结点,平衡因子为 0 printf(bt->data);printf(bt->bf); return 1; } else { //有左、右子树的结点,其平衡因子为左、右子树高度之差 hl = Computerbf(bt->lchild); hr = Computerbf(bt->rchild); bt->bf = hl-hr; printf(bt->data); printf(bt->bf); return (1+(hl>hr ? hl:hr)); } }

  1. 请编写一个双向起泡的排序算法,即每一趟通过每两个相邻的关键字进行比较,产生最小和最大的元素。
copy
void Bubble_Sort2(int a[],int n) { //相邻两趟向相反方向起泡的冒泡排序算法 low = 0; high = n-1; //冒泡的上下界 change = 1; while(low < high && change) { change = 0; //设不发生交换 for(i = low;i < high;i++) //从上向下起泡 if(a[i] > a[i+1]) { a[i]<->a[i+1]; change = 1; } high--; //修改上界 for(i = high; i>low; i--) //从下向上起泡 if(a[i] <a[i-1]) { a[i]<->a[i-1]; change = 1; } low++; //修改下界 } }
posted @   梁君牧  阅读(1993)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
🚀