题目来自摘自《22王道考研的数据结构》, 仅用作本人复习参考用
题目1
- 从顺序表中删除具有最小值的元素(假设唯一), 并由函数返回被删元素的值.空出的位置由最后一个
元素填补, 若顺序表为空,则显示出错信息并退出运行.
bool Del_Min(SqList &L, ElemType &value)
{
if(!L.length)
{
printf("error msg");
return false;
}
int pos = 0;
int min = L.data[0];
for(int i = 0; i < L.length; ++i)
if(min > L.data[i]) pos = i, min = L.data[i];
value = min;
if(pos != L.length - 1) L.data[pos] = L.data[L.length - 1]; // 这里的if可以不必进行判断,因为就算是最后一个元素,也会在下面--中被删除.
L.length--;
return true;
}
题目2
- 设计一个高效的算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1).
void Reverse(sqList &L)
{
int i = 0, j = L.length - 1;
while(j > i)
swap(L.data[i++], L.data[j--]);
}
题目3
- 对长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素 */
void del_x_1(Sqlist &L, Elemtype x) // 解法1 直接删除法
{
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;
}
void del_x_2(Sqlist &L, Elemtype x) // 解法2 构建法
{
int k = 0;
for(int i = 0; i < L.length; ++i)
if(L.data[i] != x) L.data[i - k] = L.data[i];
else ++k;
L.length = L.length - k;
}
题目4
- 从有序顺序表删除其值在给定值s与t之间(要求s < t)的所有元素, 若s或t不合理或顺序表为空,则显示出错信息并退出运行
//注意:这里s和t不一定是顺序表中的元素, 只是给定的这个范围.
bool fun(Sqlist &L, Elemtype s, Elemtype t)
{
int i, j;
if(s >= t || !L.length) return false;
for(i = 0; i < L.length && L.data[i] < s; ++i); // 寻找大于等于s的第一个元素.
if(i > L.length) return false;
for(j = i; j < L.length && L.data[j] <= t; ++j); // 寻找大于t的第一个元素
while(j < L.length) L.data[i++] = L.data[j++];
L.length = i;
return true;
}
题目5
- 从顺序表中删除其值在给定值s与t之间(包含s和t, 要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示错误并退出 */
bool fun(Sqlist &L, Elemtype s, Elemtype t)
{
if(!L.length || s >= t) return false;
int k = 0;
for(int i = 0; i < L.length; ++i)
if(L.data[i] < s || L.data[i] > t) L.data[k++] = L.data[i];
L.length = k;
return true;
}
题目6
- 从有序顺序表中删除所有其值重复的元素, 使表中所有元素均不相同(Lc26)*/
bool fun(Sqlist &L)
{
if(!L.length) return false;
int k = 0;
for(int i = 0; i < L.length; ++i)
if(!k || L.data[i] != L.data[k - 1]) L.data[k++] = L.data[i];
L.length = k;
}
题目7
- 将两个有序顺序表合并为一个新的有序顺序表, 并由函数返回结果顺序表 */
Sqlist Merge(Sqlist &L1, Sqlist &L2)
{
Sqlist L;
int n1 = 0, n2 = 0, l_n = 0;
while(n1 < L1.length && n2 < L2.length)
{
if(L1[n1] < L2[n2]) L[l_n++] = L1[n1++];
else L[l_n++] = L2[n2++];
}
while(n1 < L1.length) L[l_n++] = L1[n1];
while(n2 < L2.length) L[l_n++] = L2[n2];
L.length = l_n;
return L;
}
题目8
- 已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3,…,bn).试编写一个函数,将数组中两个顺序表的位置互换, 即将(b1,b2,b3,…,bn)放到(a1,a2,a3,…,am)的前面 .
相关题目: Acwing 77. 翻转单词顺序
void Reverse(int *Arr, int l, int r)
{
int i = l, j = r;
while(i < j) swap(Arr[i++], Arr[r--]);
}
void fun(int *arr, int m, int n)
{
Reverse(arr, 0, m + n - 1);
Reverse(arr, 0, n - 1);
Reverse(arr, n, m + n - 1);
}
题目9
- 线性表(a1,a2,a3,…,an)中的元素递增有序切按顺序存储于计算机内.要求设计一个算法,完成用最少时间在表中查找数值为x的元素, 若找到,则将其与后继元素位置相交换, 若找不到则将其插入表中并使表中顺序仍然递增有序 */
void fun(Sqlist &L, Elemtype x)
{
int l = 0, r = L.length - 1;
if(x > L.data[r]) // 特判, 若此时比最大一个元素大, 直接插入最后
{
L.data[r + 1] = x;
L.length++;
return;
}
while(r > l) // 二分查找找到第一个大于等于x的元素
{
int mid = (l + r) / 2;
if(L.data[mid] >= x) r = mid;
else l = mid + 1;
}
if(L.data[l] == x) // 找到
{
if(l == L.length - 1) return; // 最后一个元素并无后继
swap(L.data[l], L.data[l + 1]);
}
else // 找不到
{
for(int i = L.length; i > l; --i) L.data[i] = L.data[i - 1];
L.data[l] = x;
L.length++;
}
}
//关于二叉树
//二叉树的创建以及递归和非递归遍历
#include <iostream>
#include<iomanip>
#include<stack>
using namespace std;
typedef char TElemtType;
//二叉树的二叉链表存储表示
typedef struct BiTNode
{
TElemtType data; //结点数据域
struct BiTNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//先序创建二叉树
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符,创建二叉链表表示树T
TElemtType ch;
cin>>ch;
if(ch=='#') T=NULL; //递归结束,建空树
else
{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
}
}
//二叉树的递归和非递归遍历
//先序递归遍历
void PreOrderTraverse(BiTree T)
{
if(T)
{
cout<<setw(4)<<T->data;
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
//先序非递归遍历
void PreOrder(BiTree T)
{
stack<BiTree>S;
BiTree p,q;
p=T;
q=new BiTNode;
while(p||!S.empty())
{
if(p) //p非空指针进栈,输出根结点,遍历左子树
{
cout<<setw(4)<<p->data;
S.push(p);
p=p->lchild;
}
else //p空指针退栈,遍历右子树
{
q=S.top();
S.pop();
p=q->rchild;
}
}
}
//中序递归遍历
void InOrderTraverse(BiTree T)
{
if(T)
{
InOrderTraverse(T->lchild);
cout<<setw(4)<<T->data;
InOrderTraverse(T->rchild);
}
}
//中序非递归遍历
void InOrder(BiTree T)
{
stack<BiTree>S;
BiTree p,q;
p=T;
q=new BiTNode;
while(p||!S.empty())
{
if(p) //p非空指针进栈,遍历左子树
{
S.push(p);
p=p->lchild;
}
else //p空指针进栈,访问根节点,遍历右子树
{
q=S.top();
S.pop();
cout<<setw(4)<<q->data;
p=q->rchild;
}
}
}
//后序递归遍历
void PostOrderTraverse(BiTree T)
{
if(T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<setw(4)<<T->data;
}
}
//后序非递归遍历
void PostOrder(BiTree T)
{
if(T==NULL)
return;
stack<BiTree>S;
BiTree pCur,pLastVisit;
//pCur :当前访问结点 pLastVisit:上次访问结点
pCur=T;
pLastVisit=NULL;
//先把pCur移到左子树最下边
while(pCur)
{
S.push(pCur);
pCur=pCur->lchild;
}
while(!S.empty())
{
//走到这里,pCur都是空,并且已经遍历到左子树低底(看成扩充的二叉树,则空,也是某棵树的左孩子)
pCur=S.top();
S.pop();
//一个根结点被访问的前提是 ,该结点无右子树或者右子树已经北方问过
if(pCur->rchild==NULL||pCur->rchild==pLastVisit)
{
cout<<setw(4)<<pCur->data;
//修改最近被访问的结点
pLastVisit=pCur;
}
/*这里的else可以换成带条件的else if
else if(pCur->lchild==pLastVisit) 若左子树刚刚被访问过,则需要先进入右子树(根结点需要再次入栈)*/
else
{
//根结点再次入栈
S.push(pCur);
//进入右子树,且可以肯定右子树一定不为空
pCur=pCur->rchild;
while(pCur)
{
S.push(pCur);
pCur=pCur->lchild;
}
}
}
}
//层序遍历
void LevelTraverse(BiTree T)
{
queue<BiTree>Q;
Q.push(T);
while(!Q.empty())
{
T=Q.front();
Q.pop();
cout<<setw(4)<<T->data;
if(T->lchild)
Q.push(T->lchild);
if(T->rchild)
Q.push(T->rchild);
}
}
//非递归程序判断一个二叉树是否是完全二叉树
void IsCompleteTree(TreeNode* root)
{
queue<TreeNode*>que;
bool falg;//标志,判断层次遍历之后到该结点是否还能有子节点,true表示之后不能有子节点了
TreeNode* tmp;
que.push(root);
while(!que.empty())
{
tmp=que.front();
que.pop();
if(flag&&tmp->lChild||tmp->rChild)
return false;
if(tmp->lChild)
que.push(tmp->lChild);
else
flag=true;
if(tmp->rChild)
{
if(flag)
return false;
else
que.push(tmp->rChild);
}
else
flag=true;
}
return true;
}
//计算叶子结点的个数
int leafCount=0;
void LeafCountBinaryCount(Node *node)
{
if(node==NULL)
{
return ;
}
if(node->lChild==NULL&&node->rChild==NULL)
{
leafCount++;
}
LeafCountBinaryCount(node->lChild);
LeafCountBinaryCount(node->rChild);
return ;
}
//计算二叉树高度
int depth(TreeNode* root)
{
if(!root)
return 0;
int left=depth(root->left);
int right=depth(root->right);
return max(left,right)+1;
}
//非递归求二叉树的高度
// 交换二叉树根结点的左右子树
TreeNode* InvertTree(TreeNode* root)
{
if(!root)
return NULL;
TreeNode* temp_left=root->left;//保护现场,防止root->left修改后丢失
root->left=InvertTree(root->right);
root->right=InvertTree(temp_left);
return root;
}
// 求解给定关键字在二叉树中所在层数
int searchBST(TreeNode* root,int val)
{
int num=0;
while(root)
{
num++;
if(root->val==val)
return num;
else if(root->val>val)
{
if(!root->left)
return 0;
root=root->left;
}
else
{
if(!root->right)
return 0;
root=root->right;
}
}
return 0;
}
// 计算二叉树的最大宽度
int treeWidth(BTNode *root)
{
if(root==NULL)
return 0;
int nLastLevelWidth=0;//记录上一层的宽度
int nCurLevelWidth=0;//记录当前层的宽度
queue<BTNode*>Q;
Q.push(root);//将根结点入队列
int nWidth=1;//二叉树的宽度
nLastLevelWidth=1;
BTNode *pCur=NULL;
while(!Q.empty())
{
while(nLastLevelWidth!=0)//nLastLevelWidth代表上一层的宽度,控制上一层所有结点的孩子进队
{
pCur=Q.front();//取出对头元素
Q.pop();
if(pCur->left!=NULL)
Q.push(pCur->left);
if(pCur->right!=NULL)
Q.push(pCur->right);
nLastLevelWidth--;
}
nCurLevelWidth=Q.size();//此时也是上一层所有的结点个数
nWidth=nCurLevelWidth>nWidth?nCurLevelWidth:nWidth;
nLastLevelWidth=nCurLevelWidth;
}
return nWidth;
}
// 将一棵二叉树自下向上,从右往左遍历输出
void InvertLevel(BTNode* root)
{
stack<BTNode*>S;
Queue<BTNode*>Q;
BTNode* pCur;
if(root!=NULL)
{
Q.push(root); //树不空,根结点进队
while(!Q.empty()) //队不空
{
pCur=Q.front(); //出队,进栈
Q.pop();
S.push(pCur);
if(pCur->lChild) //子女不空,就入队
Q.push(pCur->lChild);
if(pCur->rChild)
Q.push(pCur->rChild);
}
while(!S.empty())
{
pCur=S.top();
S.pop();
cout<<pCur->data<<'\t';
}
}
}
// 计算一棵给定二叉树的所有的双分支结点的个数
int dsonNodes(TreeNode* root)
{
if(root==NULL)
return 0;
else if(root->lChild!=NULL&&root->rChild!=NULL)
return dsonNodes(root->lChild)+dsonNodes(root->rChild)+1;
else
return dsonNodes(root->lChild)+dsonNodes(root->rChild);
}
//将给定的表达式二叉树转换为等价的中缀表达式
// 算法思想:除根结点和叶子结点外,遍历到其他结点时再遍历左子树之前加上括号,遍历完右子树加上括号
void BiTreeExp(TreeNode* root)
{
BiTreeToExp(root,1);//根的高度为1
}
void BiTreeToExp(TreeNode* root,int depth)
{
if(root==NULL)
return; //空结点返回
else if(root->left==NULL&&root->right==NULL) //若为叶子结点
cout<<root->data; //输出操作数,不加括号
else
{
if(deep>1) //若又子表达式则加1层括号
cout<<'(';
BiTreeToExp(root->left,deep+1);
cout<<root->data; //输出操作符
BiTreeToExp(root->right,deep+1); //若又子表达式则加1层括号
if(deep>1)
cout<<')';
}
}