冒泡排序 T=O(n^2),S=O(1)

61 篇文章 2 订阅
22 篇文章 1 订阅

1 冒泡排序 T=O(n^2),S=O(1)

1. 1 从前向后比,最大值向后移

//j =0从前向后比,最大值向后移
void BubbleSort(int arr[],int n) {
	for (int i = 0; i < n - 1; i++) //n个数,需n-1趟冒泡
		for (int j = 0; j < n - 1 - i; j++) //从前向后比较,将最大的移动到最后面,后面逐渐有序,每趟比较n-1-i-1次
			if (arr[j] > arr[j + 1]) swap(arr[j], arr[j + 1]);
}

1.2 从后向前比,最小值向前移

//j =n-1 从后向前比,最小值向前移
void BubbleSort2(int arr[], int n) {
for (int i = 0; i < n - 1; i++) //n个数,需n-1趟冒泡
for (int j = n-1; j > i; j–) //从前向后比较,将最大的移动到最后面,后面逐渐有序,每趟比较n-1-i-1次
if (arr[j - 1] > arr[j]) swap(arr[j], arr[j - 1]);
}

1.3 优化提高效率,一旦有序,立即结束排序

//优化提高效率,一旦有序,立即结束排序
void BubbleSort3(int arr[], int n) {
	int flag;
	for (int i = 0; i < n - 1; i++) {//n个数,需n-1趟冒泡
		flag = false;
		for (int j = 0; j < n - 1 - i; j++) //从前向后比较,将最大的移动到最后面,后面逐渐有序,每趟比较n-1-i-1次
			if (arr[j] > arr[j + 1]) {
				swap(arr[j], arr[j + 1]);
				flag = true; //发生交换,flag = true;
			}
			if (flag == false)//如果falg=false说明,没有发生交换,说明有序,直接退出函数
				return;
		}
}

1.4 冒泡,单链表排序,无头结点

//冒泡,单链表排序,无头结点
ListNode* BubbleSort_ListNoHead(ListNode* head) {
	ListNode* q = head; //没有头结点,head指向第一个元素
	ListNode* tail = NULL; //记录,n-1-i的位置上,即后面已经有序的位置

	while (head->next != tail) {
		q = head;
		while (q->next != tail) {
			if (q->val > q->next->val) swap(q->val,q->next->val);
			q = q->next;
		}
		tail = q; //记录,n-1-i的位置上,即后面已经有序的位置
	}
	return head;
}

**指针:**通常使用“头指针”来标识一个链表,如单链表L,头指针为NULL的时表示一个空链表。链表非空时,头指针指向的是第一个结点的存储位置。

**头结点:**在单链表的第一个结点之前附加一个结点,称为头结点。头结点的Data域可以不设任何信息,也可以记录表长等相关信息。若链表是带有头结点的,则头指针指向头结点的存储位置。

**结论:**无论是否有头结点,头指针始终指向链表的第一个结点。如果有头结点,头指针就指向头结点(只不过头结点的数据域为空而已)。

在这里插入图片描述

//不带头结点的链表,在表头插入节点
x->next=head;
head=x;

//不带头结点的链表,在表头以外的地方插入结点
x->next=p->next;
p->nexy=x;

//带头结点的链表,在第一个位置插入节点
x->next=p->next;
p->nexy=x;

//带头结点的链表在其他位置插入节点
x->next=p->next;
p->nexy=x;

这时你会发现不带头结点的两种情况操作步骤不一样,而带头结点的两种情况步骤是一样的。
**所以带头结点的单链表插入更简单,更有健壮性。**当然你会问为什么要区分,我们两种都会的化可以根据实践要求来选择合适的一种使用。

//创建单链表,无头结点

struct ListNode {
	int val;
	struct ListNode* next;
	ListNode() :val(0), next(nullptr) {}//构造函数,并初始化参数列表
	ListNode(int x) :val(x), next(nullptr) {}//构造函数,并初始化参数列表
};
//创建单链表,无头结点
ListNode* createList_NoHead(int arr[],int n) {
	ListNode* head = new ListNode(arr[0]);//没有头结点,第一个结点就是第一个元素
	ListNode* p = head;
	for (int i = 1; i < n; i++) {//第一个元素是头,从第二个元素开始
		ListNode* q = new ListNode(arr[i]);
		p->next = q;
		p = p->next;
	}
	return head;//返回第一个结点(第一个元素)
}
//打印单链表,无头结点
void PrintList_noHead(ListNode* L) {
	while (L != NULL) {
		cout << L->val <<" ";
		L = L->next;
	}
	cout << endl;
}

1.5 冒泡,单链表排序,有头结点

//冒泡,单链表排序,有头结点
ListNode* BubbleSort_ListWithHead(ListNode* head) {
	ListNode* q = head->next; //有头结点,head->next指向第一个元素
	ListNode* tail = NULL;

	while (head->next->next != tail) {
		q = head->next;
		while (q->next != tail) {
			if (q->val > q->next->val) swap(q->val, q->next->val);
			q = q->next;
		}
		tail = q;
	}
	return head;
}

创建单链表,有头结点

struct ListNode {
	int val;
	struct ListNode* next;
	ListNode() :val(0), next(nullptr) {}//构造函数,并初始化参数列表
	ListNode(int x) :val(x), next(nullptr) {}//构造函数,并初始化参数列表
};
//创建单链表,有头结点
ListNode* createList_WithHead(int arr[], int n) {
	ListNode* head = new ListNode(13);//头结点可以是任意数字,也可以设为表长,头结点不是第一个元素,不记作表长
	ListNode* p = head;
	for (int i = 0; i < n; i++) {//有头结点,第一个元素从0开始
		ListNode* q = new ListNode(arr[i]);
		p->next = q;
		p = p->next;
	}
	return head->next;//返回第一个元素结点
}

1.6 完整程序测试

#include<iostream>
using namespace std;
struct ListNode {
	int val;
	struct ListNode* next;
	ListNode() :val(0), next(nullptr) {}//构造函数,并初始化参数列表
	ListNode(int x) :val(x), next(nullptr) {}//构造函数,并初始化参数列表
};

//j =0从前向后比,最大值向后移
void BubbleSort(int arr[],int n) {
	for (int i = 0; i < n - 1; i++) //n个数,需n-1趟冒泡
		for (int j = 0; j < n - 1 - i; j++) //从前向后比较,将最大的移动到最后面,后面逐渐有序,每趟比较n-1-i-1次
			if (arr[j] > arr[j + 1]) swap(arr[j], arr[j + 1]);
}
//j =n-1 从后向前比,最小值向前移
void BubbleSort2(int arr[], int n) {
	for (int i = 0; i < n - 1; i++) //n个数,需n-1趟冒泡
		for (int j = n-1; j > i; j--) //从前向后比较,将最大的移动到最后面,后面逐渐有序,每趟比较n-1-i-1次
			if (arr[j - 1] > arr[j]) swap(arr[j], arr[j - 1]);
}
//优化提高效率,一旦有序,立即结束排序
void BubbleSort3(int arr[], int n) {
	int flag;
	for (int i = 0; i < n - 1; i++) {//n个数,需n-1趟冒泡
		flag = false;
		for (int j = 0; j < n - 1 - i; j++) //从前向后比较,将最大的移动到最后面,后面逐渐有序,每趟比较n-1-i-1次
			if (arr[j] > arr[j + 1]) {
				swap(arr[j], arr[j + 1]);
				flag = true; //发生交换,flag = true;
			}
			if (flag == false)//如果falg=false说明,没有发生交换,说明有序,直接退出函数
				return;
		}
}

//冒泡,单链表排序,无头结点
ListNode* BubbleSort_ListNoHead(ListNode* head) {
	ListNode* q = head; //没有头结点,head指向第一个元素
	ListNode* tail = NULL;

	while (head->next != tail) {
		q = head;
		while (q->next != tail) {
			if (q->val > q->next->val) swap(q->val,q->next->val);
			q = q->next;
		}
		tail = q;
	}
	return head;
}

//冒泡,单链表排序,有头结点
ListNode* BubbleSort_ListWithHead(ListNode* head) {
	ListNode* q = head->next; //有头结点,head->next指向第一个元素
	ListNode* tail = NULL;

	while (head->next->next != tail) {
		q = head->next;
		while (q->next != tail) {
			if (q->val > q->next->val) swap(q->val, q->next->val);
			q = q->next;
		}
		tail = q;
	}
	return head;
}
//创建单链表,无头结点
ListNode* createList_NoHead(int arr[],int n) {
	ListNode* head = new ListNode(arr[0]);//没有头结点,第一个结点就是第一个元素
	ListNode* p = head;
	for (int i = 1; i < n; i++) {//第一个元素是头,从第二个元素开始
		ListNode* q = new ListNode(arr[i]);
		p->next = q;
		p = p->next;
	}
	return head;//返回第一个结点(第一个元素)
}
//创建单链表,有头结点
ListNode* createList_WithHead(int arr[], int n) {
	ListNode* head = new ListNode(13);//头结点可以是任意数字,也可以设为表长,头结点不是第一个元素,不记作表长
	ListNode* p = head;
	for (int i = 0; i < n; i++) {//有头结点,第一个元素从0开始
		ListNode* q = new ListNode(arr[i]);
		p->next = q;
		p = p->next;
	}
	return head->next;//返回第一个元素结点
}

void Print(int A[], int n) {
	for (int i = 0; i < n; i++)
		cout << A[i] << " ";
	cout << endl;
}

//打印单链表,无头结点
void PrintList_noHead(ListNode* L) {
	while (L != NULL) {
		cout << L->val <<" ";
		L = L->next;
	}
	cout << endl;
}
//打印单链表,有头结点
//(用于直接返回head,如果带头结点返回head->next,则使用无头结点打印函数)
void PrintList_withHead(ListNode* L) {
	while (L->next != NULL) {
		cout << L->next->val << " ";
		L = L->next;
	}
	cout << endl;
}

int main() {
	int arr[13] = { -1,0,-2 ,1,2,1,2,3,9,6,7,2,0 };

	//ListNode* L = createList_NoHead(arr,13);
	ListNode* L = createList_WithHead(arr, 13);
	PrintList_noHead(L);

	//ListNode* L2 = ButtleSort_ListNoHead(L);
	ListNode* L2 = ButtleSort_ListWithHead(L);
	PrintList_noHead(L2);

	return 0;
};

在这里插入图片描述

1.7 单链表,转成数组,再借助库函数sort()排序,T=O(nlog2n),S=O(n)

sort()函数需要头文件 #include

ListNode* ListSort2(ListNode* head) {
	vector<int> res;
	ListNode* p = head;
	while (p) {//遍历链表,将节点值加入数组
		res.push_back(p->val);
		p = p->next;
	}
	//对数组元素排序
	sort(res.begin(),res.end());
	p = head;
	//将数组元素依次加入链表
	for (int i = 0; i < res.size(); i++) {
		p->val = res[i]; 
		p = p->next;
	}		
	return head;
}

复杂度分析:

时间复杂度:O(nlog2n),sort函数一般为优化后的快速排序,复杂度为O(nlog2n);
空间复杂度:O(n),存储链表元素值的辅助数组长度n.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-G-B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值