数据结构 | C++ | 快排和折半查找后插入

顺序表:

0.头文件

using namespace std;
#include 
#include
#include

1.结点类和顺序表类: 

vector的好处就是析构函数只要:s.clear();

//结点类
struct Student
{
	int score;  
	string name;
};

//顺序表类
class Seqlist
{
public:
	Seqlist();															//构造函数
	~Seqlist() {s.clear();}											//析构函数
	int size();															//返回元素个数
	void Traverse();													//遍历函数

	void QuickSort(int i,int j);									//快排的递归调用
	int Partition(int i, int j);										//快排的一次划分算法

	void BiSearch();					//折半插入排序

private:

	vector  s;
	int length;
};

 

2.构造函数

//构造函数
Seqlist::Seqlist()
{
	Student m;
	cout << "输入的学生成绩个数";
	cin >> length;//length  即为最大容量
	for (int i = 0; i < length; i++)
	{
		cout << "输入第" << i + 1 << "位学生姓名: ";
		cin >> m.name;
		cout << "输入" << i + 1 << "位学生成绩: ";
		cin >> m.score; cout << endl;

		s.push_back(m);
	}
}

 3.求表长,遍历函数

//返回元素个数
int Seqlist::size()
{

	return s.size();
}

//遍历函数
void Seqlist::Traverse() 
{
	for (int i = 0; i < s.size(); i++)//修改前:i

 

*4.快排

temp指第一个元素,用来存放标记值;

i是0,表示表第一个元素;

j是length()-1,表示最后一个元素.

递归要避开枢轴,否则会溢出栈

③之前的bug:如int temp = s[i].score;改变了成绩的次序,未改变学生的次序

//快排的一次划分算法
int Seqlist::Partition(int i, int j)
{
	Student temp = s[i];        //将首元素的key设为关键字  
	while (i= temp.score)
		{
			j--;				//j一直循环到一个小于temp的值
		}
		if (i

*5 折半查找

 



//折半查找算法
void Seqlist::BiSearch()
{
	int low = 0; 
	int high = s.size() - 1;
	int find = 0;
	int mid;

	Student m;
	cout << "输入新同学姓名";
	cin >> m.name;
	cout << "输入新同学成绩";
	cin >> m.score;

	if(m.score>s[s.size()-1].score)			//m.score大于最大的,直接尾部加入
	{
		s.push_back(m);//如果不是vector,而是数组,此处应该有length++;下面一样.
	}
	else if(m.score s[mid].score)
			{
				low = mid + 1;
				if (low == mid)
				{
					s.insert(s.begin() + mid , m);
				}
				find = 1;							//终止循环
			}
			else										//插入值与数组某元素相等
			{
				 find = 1;							//终止循环
				 s.insert(s.begin() + mid, m);
			}	
		}	
	}
}


 

6.main()函数

int main()
{
	Seqlist s1;
	s1.Traverse();

	//顺序表快排测试
	s1.QuickSort(0, s1.size() - 1);
	cout << "快速排序后"<

 


链式存储的排序算法:

0.头文件

using namespace std;
#include 
#include

1.节点类和链表类: 

 为了在main()传参调用快速排序算法,不得不把Student *elem 改为public.


//结点类
struct Student
{
	 int score;  
	Student *next=nullptr;					//结点类的*next 需要初始化,否则显示"读取访问权限冲突"
};

//链表类
class Linklist
{
public:
	Linklist();															//构造函数
	~Linklist();															//析构函数
	void CreateLinklist();											//创建链表
	int size();															//返回元素个数
	void Traverse();													//遍历函数

	
	Student *Partition(Student *pBegin, Student *pEnd);										//快排的一次划分算法
	void QuickSort(Student *pBegin, Student *pEnd);									//快排的递归调用
	
	void BiSearch();					//折半插入排序


	Student *elem;
};

2.构造函数与析构函数 

①elem new出头结点后,不需要为其数据域赋初值,只要将next指针域置nullptr即可

//构造函数
Linklist::Linklist()
{
	elem = new Student;	
	elem->next = nullptr;				//常量NULL实际上是数字0,可能引起误用.作为解决方案,nullptr是代表空指针的字面值常量
}

//析构函数
Linklist::~Linklist()
{
	Student *p = elem;
	
	while (p)
	{
		Student *q = p;
		p = p->next;
		delete q;
	}
	elem = nullptr;
	//头删法
}

3.创建链表

  也可以写成带参构造函数.

//创建链表
void Linklist::CreateLinklist()
{
	Student *p, *q;
	p = elem; 
	 int n;
	cout << "输入学生个数\n";
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		q = new Student;

		cout << "输入" << i + 1 << "位学生成绩: ";
		cin >> q->score;cout << endl;
		p->next = nullptr;

		p->next = q;
		p = p->next;
	}
	cout << "输入成功!\n";
}

 4.表长和遍历


//学生个数
int Linklist::size()
{
	int i = 0;
	Student *p = elem->next;				//p指向首元结点
	while (p)
	{
		p = p->next;
		i++;
	}
	return i;
}

//遍历函数
void Linklist::Traverse()
{
	
	Student *q = elem->next;			//首元结点
	
	for (int i = 0; i < this->size(); i++)
	{
		cout << "第" << i + 1 << "位学生成绩:" << q->score << endl;
		q = q->next;
	}
	
}

*5链表类型的快排算法 

①i指针之前的值都小于标记值

i~j之间的值都大于标记值

j之后的值都未判断大小,当j==nullptr,意味着一次排序结束.

②※递归算法QuickSort(Student *pBegin, Student *pEnd) 中,

注意if()内的第一行,输入的

Partition(Student *pBegin, Student *pEnd)

形参来自于

QuickSort(Student *pBegin, Student *pEnd)

的形参,

究其根本,是由

main()中(a1.elem->next, nullptr)传递实参.

 




//快排的一次划分算法(两个指针均向后移动)
Student* Linklist::Partition(Student *pBegin, Student *pEnd)//pBegin的实参是elem,pEnd的实参是最末元素的next,也就是nullptr
{
	Student *i = pBegin;						//首元结点
	Student *j = i->next;
	int flag = pBegin->score;				//基准数字

	while (j != pEnd)									//循环到j是最后一个元素的next域(NULL状态)
	{
		if (j->score < flag)
		{
			i = i->next;
			
			swap(i->score, j->score);
		}
		j = j->next;
	}
	swap(i->score, pBegin->score);
	return i;
}

//快排的递归
void Linklist::QuickSort(Student *pBegin, Student *pEnd)
{
	if (pBegin!=pEnd) 
	{
		Student *pivot = Partition(pBegin,pEnd);				//此处输入的是形参
		QuickSort(pBegin, pivot);
		QuickSort(pivot->next, pEnd);
	}
}





6.main()

int main()
{

	Linklist a1;
	a1.CreateLinklist();

	//返回学生数
	cout << "学生有" << a1.size() << "位\n";

	//遍历
	a1.Traverse(); cout << endl;

	
	//快排
	a1.QuickSort(a1.elem->next, nullptr);
	cout << "快排后:\n";
	a1.Traverse();
	

	system("pause");
	return 0;
}

7.Bug

void Linklist::text()
{
    Student *p = elem->next;
    p->score = 100;
    Traverse();
}

错误,不能直接修改结点的值

 

 

你可能感兴趣的:(数据结构)