dataStructure

一、2019年B:

在这里插入图片描述在这里插入图片描述

41、 设计一算法,从顺序表中删除最小值的元素(设顺序表中元素均不相同)。空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行。

/*
设计一算法,从顺序表中删除最小值的元素(设顺序表中元素均不相同)。
空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行。
*/
//若删除成功,则返回true;否则返回false
bool del_Min(sqList &L){
	if(L.length==0)
		return false;	//表空,返回false 
	minValue = L.data[0];//假定0号元素的值最小
	int minValueIndex = 0;		
	for(int i=1;i<L.length;i++) //循环,寻找具有最小值得元素
		if(L.data[i] < minValue){
			minValue = L.data[i];
			minValueIndex = i;
		}
	L.data[minValueIndex] = L.data[L.length-1];	//空出的元素由最后一个元素填补
	L.length--;
	return true;	//此时,value为最小值
}

在这里插入图片描述
扩展功能:假设无序状态
先对链表进行排序在删除数相等的结点

void sortDel()                              //排序+删除
{
    pStu p, q, temp1;
    int temp;
    p = head;
    for( p ; NULL != p->Next ; p = p->Next )
    {
        for( q = p->Next ; NULL != q->Next ; q = q->Next)
        {
            if( p->Next->a > q->Next->a )
            {
                temp = p->Next->a;
                p->Next->a = q->Next->a;
                q->Next->a = temp;
            }
        }
 
    }
 
/************以上是排序,下面是去重**********************/
    p = head->next;
    q = p->next;
    while(NULL != q)
    {
        if(p->a == q->a)
        {
            temp1 = q;
            p->next = q->next;
            q = q->next;
            delete(temp1);
        }
        else
        {
            q = q->next;
            p = p->next;
        }
        
    }
}

在这里插入图片描述
在这里插入图片描述

/**
已知一个队列 Q,其结点的数据域为一个自然数。输入一个自然数
n,与队头结点数据配对。如果相等,则删除队头结点;如果不相等或队列为空,
则把 n 插入队列。如果输入数为 0,则结束处理
队列的 ADT 函数有:
	void enQueue(Queue q,ElemType e); //元素 e 入队
	ElemType deQueue(Queue q,ElemType e); //出队,将队头元素放入 e
	int isEmpty(Queue q); //判断队空,返回值是1表示队空,返回值0表示非空
	void GetHead(Queue q, ElemType x);//获取队首元素,放入 x
*/

//输入数据为n 
void dealQ(Queue q,int n)
{
	if(n == 0)
	{
		return 0;//如果输入数为 0,则结束处理
	}
	if(isEmpty(q)){
		ElemType s;
		s.data = n;
		enQueue(&q,s);
		return;
	}
	ElemType frontNode;
	GetHead(&q,&frontNode);
	if(frontNode.data == n)//如果相等
	{
		//删除队头节点
		 deQueue(&q,&frontNode);
	}
	else
	{
		ElemType s;
		s.data = n;
		enQueue(&q,s);
	}
} 

在这里插入图片描述

/*
设非空二叉树采用二叉链表存储结构,根结点的指针为 bt。试利用二叉树
的中序遍历,编写判断该二叉树是否为二叉排序树的非递归算法。
*/
/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Checker {
public:
	bool checkBST(TreeNode* root)
   {
	stack<TreeNode*>tmpStack;
	TreeNode* pNode=root;
	int minVal=-1000;//初始化一个最小值;
	if (root==NULL)
	{
		return 1;//空树是二叉排序树;
	}
	else
	{
		while(pNode||!tmpStack.empty())
		{
		  while(pNode)
			{
				tmpStack.push(pNode);//左孩子入栈;	
				pNode=pNode->left;
			}
			if (!tmpStack.empty())
			{
				if (minVal>tmpStack.top()->val)
				{
					return 0;
				}
				minVal=tmpStack.top()->val;
				pNode=tmpStack.top()->right;
				tmpStack.pop();//出栈;
			}
		}
		return 1;
	}
  }
};

二、2020年B:

/*
41、(20 分)如下描述一个集合的抽象数据类型 ASet,其中所有元素为正整
数,集合的基本运算包括:
(1)由整数数组a[0..n-1]创建一个集合。createset( &s,a,n): (5分) ( ○ 44 )
(2)输出一个集合的所有元素。dispset( s):(5 分)( ○ 45 )
(3)判断一个元素是否在一个集合中。inset(s,e):(5 分)( ○ 46 )
(4)求两个集合的并集。void add(s1,s2,s3):s3=s1∪s2 (5 分)( ○ 47 )
在此基础上设计了集合的顺序存储结构,请写出实现各基本运算的算法。
ADT ASet
{ 
	数据对象:D={ di | 0≤i≤n,n 为一个正整数}
	数据关系:无。
	基本运算:
		createset( &s,a,n):创建一个集合 s;
		dispset( s):输出集合 s;
		bool inset(s,e):判断 e 是否在集合 s 中
		void add(s1,s2,s3):s3=s1∪s2;  //求集合的并集
}
设计集合的顺序存储结构类型如下:
typedef struct  //集合结构体类型
{ 
	int data[MaxSize];  //存放集合中的元素,其中 MaxSize 为常量
	int length; //存放集合中实际元素个数
} Set; //将集合结构体类型用一个新类型名 Set 表示
*/

#include<iostream>
using namespace std;
const int MaxSize = 100;
typedef struct  //集合结构体类型
{ 
	int data[MaxSize];  //存放集合中的元素,其中 MaxSize 为常量
	int length; //存放集合中实际元素个数
} Set;
class ASet
{
	private:
		int D[];
	public:
		void createset(Set &s,int a[],int n); 
		void dispset(Set s);
		bool inset(Set s,int e);
		void add(Set s1,Set s2,Set &s3);
};
void ASet::createset(Set &s,int a[],int n)
{
	if(n > MaxSize)
	{
		throw "数组元素过长,溢出异常";//抛异常 
	}
	for(int i = 0;i < n;i++)
	{
		s.data[i] = a[i];
	}
	s.length = n;
}
void ASet::dispset(Set s)
{
	for(int i = 0;i < s.length;i++)
	{
		cout<<s.data[i]<<endl;
	}
}
bool ASet::inset(Set s,int e)
{
	for(int i = 0;i < s.length;i++)
	{
		if(e == s.data[i])
		{
			return true;
		}
		else{
			return false;
		}
	}
}
void ASet::add(Set s1,Set s2,Set &s3)
{
	int index = 0;
	s3.length = 0;
	bool flag = true;
	for(int i = 0;i < s1.length;i++)
	{
		for(int j = 0;j < s3.length;j++)
		{
			if(s3.data[j] == s1.data[i])
			{
				flag = false;
				break;
			}
		}
		if(flag)
		{
			s3.length++;
			s3.data[index++] = s1.data[i];
		}
		flag = true;//要进行重置 
		
	}
	for(int i = 0;i < s2.length;i++)
	{
		for(int j = 0;j < s3.length;j++)
		{
			if(s3.data[j] == s2.data[i])
			{
				flag = false;
				break;
			}
		}
		if(flag)
		{
			s3.length++;
			s3.data[index++] = s2.data[i];
		}
		flag = true;//要进行重置 
	}
}
int main()
{
	ASet aset;
	Set s;
	int arr[] = {12,3,2,9,7,8};
	aset.createset(s,arr,6);
	aset.dispset(s);
	cout<<aset.inset(s,15)<<endl;
	
	//其他测试
	cout<<"*******************"<<endl;
	Set s1,s2,s3;
	int arr1[] = {1,3,5,7,9,8};
	int arr2[] = {2,4,6,8,10,12};
	aset.createset(s1,arr1,6); 
	aset.createset(s2,arr2,6); 
	aset.add(s1,s2,s3);
	aset.dispset(s3);
	return 0;
}
/*
42、(8 分)以二叉链表作为二叉树的存储结构,编写统计二叉树的叶结点
个数算法。( ○ 48 )----->参考19B有个题 
*/
#include<iostream>
using namespace std;
 
int ans;	//叶子节点数 
 
typedef struct biTnode{
	char data;	
	struct biTnode *lc,*rc;
}biTnode,*bitree;
 
void cr_bitree(bitree &T)
{//先序建树 
		char ch;
		cin>>ch;
		if(ch=='#')	 T = NULL;//空树 
		else{
			T= new biTnode;//ch!='#',建节点 
			T->data = ch;
			cr_bitree(T->lc);// 左子树 
			cr_bitree(T->rc);// 右子树 
		}	
}
 
void find(bitree T)
{
	if(T==NULL)	return;//节点为空不计入 
	if(T->lc==NULL&&T->rc==NULL) 
		ans++;//当且仅当左右孩子为空,节点date不为空时,ans++; 
	else
	{
		find(T->lc);//找左树(左孩子) 
		find(T->rc);//找右树(右孩子) 
	}
}
 
int main()
{
		ans=0;
		bitree T;
		cr_bitree(T);
		find(T);
		cout<<ans<<endl;
		delete T;
		return 0;
}
/*
43、(12 分)如果允许在循环队列的两端都可以进行插入和删除操作。要求:
	① 写出循环队列的类型定义;(4 分)( ○ 49 )
	② 写出“从队尾删除”和“从队头插入”的算法。(8 分)( ○ 50 )
*/

#include<iostream>
using namespace std;
const int QueueSize=100;

class CirQueue
{
	public:
		CirQueue()                             //构造函数,置空队列
		{
		    front = rear = 0;
		}
		~CirQueue(){cout<<"destory";}    //析构函数
		void EnQueue(int x);                  
		int DeQueue();                         
	private:
		int data[QueueSize];                  //存放队列的数组
		int front,rear;                      //头指针与尾指针 约定fonrt指向队头元素的前一个元素 ,尾部指针指向队尾元素 
};

//从队头插入 
void CirQueue::EnQueue(int x)
{
	if((rear+1)%QueueSize==front)             //判断队列是否已满
	    cout<<"queue is full,can't put "<<x<<" into it"<<endl;
	else
	{
		//front指向头结点的前一个结点 
	    data[front]=x;                        //元素x入队
	    //此时front--才对
		front = (front - 1 + QueueSize) % QueueSize; 
	}
}

//从队尾删除 
int CirQueue::DeQueue()                    //队头元素出栈
{
	if(rear == front){                           //判断队列是否为空
	    cout<<"queue is empty"<<endl;
	    return 0;
	}
	else
	{
		int x = data[rear];//保存待删除的值
	    rear = (rear - 1 + QueueSize) % QueueSize;        
		return x;       
	}
}
//测试 
int main()
{
	CirQueue Q;
	Q.EnQueue(1);
	Q.EnQueue(2);
	Q.EnQueue(3);
	cout<<Q.DeQueue()<<endl;
	cout<<Q.DeQueue()<<endl;
	cout<<Q.DeQueue()<<endl;
	Q.DeQueue();
    return 0;
}

/*
44、(10)有人设计如下算法用于删除整数顺序表 L 中所有值在[x,y]范围
内的元素,该算法显然不是高效的,请设计一个同样功能的高效算法。( ○ 51 )
void fun(SqList *&L,ElemType x)
{ 
	int i,j;
	for (i=0;i<L->length;i++)
	if (L->data[i]>=x && L->data[i]<=y)
	{ 
		for(j=i;j<L->length-1;j++)
			L->data[j]=L->data[j+1];
			L->length--;
	}
}
*/

#include<iostream>
using namespace std;
const int MaxSize = 100;
struct SqList{
	int length;
	int data[MaxSize];
};


//原题给的代码 
void fun(SqList*& L,int x,int y)
{ 
	int i,j;
	for (i=0;i<L->length;i++)
	{
		if (L->data[i]>=x && L->data[i]<=y)
		{ 
			//删除,将后面的值往前移 
			for(j=i;j<L->length-1;j++)
			{
				L->data[j]=L->data[j+1];
			}
			L->length--;
			i--;
		}
	}
		
}
//优化后的代码 
void funSenior(SqList*& L,int x,int y)
{ 
	int i,j,count = 1,jTemp;
	for (i=0;i<L->length;i++)
	{
		if (L->data[i]>=x && L->data[i]<=y)
		{ 
			//删除,将后面的值往前移 
			j = i + 1;
			if(j < L->length)
			{
				L->data[i] = L->data[j];
				while(j < L->length && L->data[i]>=x && L->data[i]<=y)
				{
					count++;//表示减少一次全体平移 
					j++;
					L->data[i] = L->data[j];
					
				}
				//剩下的直接全部前移 
				jTemp = j + 1;
				j = i + 1;
				while(jTemp < L->length)
				{
					L->data[j] = L->data[jTemp];
					j++;
					jTemp++;
				}
				L->length -= count;
				i--;
				count = 1;//重置 
			}
		}
	} 
		
}
int main()
{
	SqList s;
	SqList * L = &s;
	for(int i = 0;i < 10;i++)
	{
		L->data[i] = i + 1;
	}
	L->length = 10;
//	fun(L,3,6);
	funSenior(L,3,6);
	for (int i = 0; i < L->length; i++)
	{
		cout << L->data[i] << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值