系列文章目录

深入浅出,408数据结构之顺序表操作详解深入理解链表:从头插法到删除操作,408考研必备!

文章目录

系列文章目录前言1、查找算法1.1 顺序查找1.1.1 在数组中进行顺序查找1.1.2 在链表中进行顺序查找

1.2 二分查找

2、排序算法2.1 冒泡排序2.1.1 数组2.1.2 链表

2.2 选择排序2.3 插入排序2.4 快速排序

总结

前言

在学习数据结构和考研中,查找算法和排序算法是基础而重要的概念。它们在解决问题和优化程序性能方面起着至关重要的作用。本文将深入探讨各种查找和排序算法,帮助您更好地理解和运用它们。

1、查找算法

1.1 顺序查找

顺序查找是一种简单直观的查找方法,它逐个比较待查找元素和数据结构中的每个元素。在实际应用中,顺序查找可以应用于数组和链表等数据结构中。

1.1.1 在数组中进行顺序查找

代码如下:

#include

//算法思路:在循环内进行条件判断

bool basicSearch(int arr[], int len, int num) {

int i;

for (i = 0; i < len; i++) {

if (arr[i] == num) {

return true;

}

}

return false;

}

int main() {

int arr[] = { 131, 127, 147, 81, 103, 23, 7, 79 };

int num = 81;

int len = sizeof(arr) / sizeof(arr[0]);//算出数组的长度

bool ret;

ret=basicSearch(arr, len, num);

if (ret == true) {

printf("找到数值%d", num);

}

else {

printf("未找到数值");

}

}

1.1.2 在链表中进行顺序查找

代码如下:

#include

#include

typedef int Elemtype;

typedef struct LNode {

Elemtype data;

struct LNode* next;

}LNode, * LinkList;

void list_tail_insert(LinkList& L) {

L = (LinkList)malloc(sizeof(LNode));

Elemtype x;

scanf("%d", &x);

LinkList r = L;

LinkList s;

while (x != 9999) {

s = (LinkList)malloc(sizeof(LNode));

s->data = x;

r->next = s;

r = s;

scanf("%d", &x);

}

r->next = NULL;

}

void print_list(LinkList L) {

L = L->next;

while (L != NULL) {

printf("%3d", L->data);

L = L->next;

}

printf("\n");

}

//算法思路:定义一个指向链表尾的指针,循环内进行条件判断,找出符合条件的结点

LinkList basicSearch(LinkList L, int num) {

LinkList r = L->next;

while (r != NULL) {

if (r->data == num) {

return r;

}

r = r->next;

}

return NULL;

}

int main() {

LinkList L;

list_tail_insert(L);

print_list(L);

int num = 4;

LinkList result;

result = basicSearch(L, num);

if (result != NULL) {

printf("该数值%d已找到\n", result->data);

}

else {

printf("该数值未找到\n");

}

return 0;

}

1.2 二分查找

二分查找是一种高效的查找算法,适用于有序数组。通过不断缩小查找范围,二分查找能够快速定位目标元素。

代码如下:

#include

//算法思路:先定义两个位置变量left和right,在循环里面,进行mid与左右的条件判断

//根据多个条件判断,修改左右变量,再去进行mid的重新赋值

int binarySearch(int arr[], int len, int num) {

int left = 0;

int right = len - 1;

while (left <= right) {

//需要每次定义mid的位置,因此放在循环内部

int mid = (left + right) / 2;

if (arr[mid] < num) {

//mid在num的左边

left = mid + 1;

}

else if (arr[mid] > num) {

//mid在num的右边

right = mid - 1;

}

else {

//找到了

return mid;

}

}

//退出循环为left>right,则为找不到

return -1;

}

int main() {

int arr[] = { 7, 23, 79, 81, 103, 127, 131, 147 };

int num = 81;

int len = sizeof(arr) / sizeof(arr[0]);

int search = 0;

search=binarySearch(arr, len, num);

printf("找到%d的索引为%d", num, search);

return 0;

}

2、排序算法

2.1 冒泡排序

冒泡排序是一种简单直观的排序算法,通过多次遍历数据,将较大(或较小)的元素逐步交换至正确的位置。

动画如下:

2.1.1 数组

代码如下:

#include

//算法思路:定义两个循环,在外循环执行进行几轮的交换,内循环执行每两个元素比较交换位置的次数

void bubbleSort(int arr[], int len) {

//外循环:表示我要执行多少轮。 如果有n个数据,那么执行n - 1 轮

for (int i = 0; i < len - 1; i++) {

//内循环:每一轮中我如何比较数据并找到当前的最大值

//-1:为了防止索引越界

//-i:提高效率,每一轮执行的次数应该比上一轮少一次。

for (int j = 0; j < len - 1 - i; j++) {

//排序后数组从小到大排序

if (arr[j] > arr[j + 1]) {

int temp = arr[j];

arr[j] = arr[j + 1];

arr[j + 1] = temp;

}

}

}

}

int main() {

int arr[] = { 2, 4, 5, 3, 1 };

int len = sizeof(arr) / sizeof(arr[0]);

bubbleSort(arr, len);

for (int i = 0; i < len; i++) {

printf("%3d", arr[i]);

}

return 0;

}

2.1.2 链表

代码如下:

#include

#include

typedef int Elemtype;

typedef struct LNode {

Elemtype data;

struct LNode* next;

}LNode,*LinkList;

void listTailCreate(LinkList& L) {

L = (LinkList)malloc(sizeof(LNode));

LinkList s;

LinkList r = L;

Elemtype x;

printf("请输入链表的数值,以9999为终\n");

scanf("%d", &x);

while (x != 9999) {

s = (LinkList)malloc(sizeof(LNode));

s->data = x;

r->next = s;

r = s;

scanf("%d", &x);

}

r->next = NULL;

}

void printList(LinkList L) {

L = L->next;

while (L) {

printf("%3d", L->data);

L = L->next;

}

printf("\n");

}

//算法思路:定义镶嵌循环,外循环表示进行了几轮,拿着链表的长度-1个结点元素进行比较

//无需知道链表的长度,由指向链表尾的指针p不为空可进行判断

//内循环表示与其他元素进行比较,条件判断符合进行位置的交换

void sortList(LinkList L) {

if (L == NULL || L->next == NULL) {

return; // 如果链表为空或只有一个元素,则无需排序

}

LinkList p, q;

for (p = L->next; p != NULL; p = p->next) {

//从p的下一个结点开始

for (q = p->next; q != NULL; q = q->next) {

if (p->data > q->data) {

// 交换 p 和 q 指向的元素

Elemtype temp = p->data;

p->data = q->data;

q->data = temp;

}

}

}

}

int main() {

LinkList L;

listTailCreate(L);

printf("创建的链表为:\n");

printList(L);

printf("排序后的链表为:\n");

sortList(L);

printList(L);

return 0;

}

2.2 选择排序

选择排序是另一种常见的排序算法,它通过多次选择最小(或最大)的元素,逐步构建有序序列。

动画如下:

代码如下:

#include

//算法思路:进行双循环,外循环表示进行了几轮比较

//内循环表示:拿着外循环指向的结点与其后面的所有元素进行比较,条件判断符合进行位置的交换

void selectSort(int arr[], int len) {

//外循环:进行了几轮比较,一共是len-1次

for (int i = 0; i < len - 1; i++) {

//内循环:拿着i和i后面的数据进行交换,所以得加1

for (int j = i + 1; j < len; j++) {

if (arr[i] > arr[j]) {

int temp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

}

}

}

}

int main() {

int arr[] = { 2, 4, 5, 3, 1 };

int len = sizeof(arr) / sizeof(arr[0]);

selectSort(arr, len);

for (int i = 0; i < len; i++) {

printf("%3d", arr[i]);

}

return 0;

}

2.3 插入排序

排序思路:将0索引的元素到N索引的元素看做是有序(依次从小到大)的,把N+1索引的元素到最后一个当成是无序(大小无顺序)的。

遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。

动画如下:

代码如下:

#include

//算法思路:先用一个循环找出无序的首元素索引,然后用嵌套循环,

//外循环进行遍历,从startIndex开始到最后一个元素,得到无序数据的每一个元素

//内循环,拿着外循环得到的元素,与有序数据的每个元素进行大小判断交换位置

void insertSort(int arr[], int len) {

//1.找到无序的那一组数组是从哪个索引开始的。

int startIndex;

for (int i = 0; i < len; i++) {

//如果前一个元素大于后一个

if (arr[i] > arr[i + 1]) {

//找到并定义无序数据的首元素索引

startIndex = i + 1;

break;

}

}

//2.遍历从startIndex开始到最后一个元素,依次得到无序的那一组数据中的每一个元素

for (int i = startIndex; i < len; i++) {

//先记录当前要插入数据的索引,防止后面操作修改i

int j = i;

//将无序的第i个元素,在有序数据中从后往前,如果后一个元素小于前一个元素,需要交换

while (j > 0) {

//符合条件进行交换

if (arr[j] < arr[j - 1]) {

int temp = arr[j];

arr[j] = arr[j - 1];

arr[j - 1] = temp;

}

j--;//继续跟前面的元素进行对比交换

}

}

}

int main() {

int arr[] = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };

int len = sizeof(arr) / sizeof(arr[0]);

insertSort(arr, len);

for (int i = 0; i < len; i++) {

printf("%3d", arr[i]);

}

return 0;

}

2.4 快速排序

排序思路:

从数列中挑出一个元素,一般都是左边第一个数字,称为 “基准数”; (如果以0索引为基准数就要end先走,如果以最大索引为基准,就要start先走)!!!!! 即3、4步步骤进行交换 创建两个指针,一个从前往后走,一个从后往前走。 先执行后面的指针,找出第一个比基准数小的数字 再执行前面的指针,找出第一个比基准数大的数字 交换两个指针指向的数字 继续偏转 直到两个指针相遇 将基准数跟指针指向位置的数字交换位置,称之为:基准数归位。 第一轮结束之后,基准数左边的数字都是比基准数小的,基准数右边的数字都是比基准数大的。 把基准数左边看做一个序列,把基准数右边看做一个序列,让这两个序列自己内部按照刚刚的规则递归排序 最后分成许多的序列递归完成最终的排序

代码如下:

#include

void quickSort(int arr[], int i, int j) {

//定义两个变量记录要查找的范围

int start = i;

int end = j;

//递归的出口,当到了出口,就不会执行下面的循环交换操作

if (start > end) {

return;

}

//记录基准数,下面的start会改变,这里是i

int baseNum = arr[i];

//利用循环找到要交换的数字

while (start != end) {

//利用end,从后往前开始找,找到比基准数小的数字

while (true) {

//异常情况或者找到了

if (end <= start || arr[end] < baseNum) {

break;

}

//不符合找到的条件,继续偏转

end--;

}

while (true) {

//异常情况或者找到了

if (end <= start || arr[start] > baseNum) {

break;

}

//不符合找到的条件,继续偏转

start++;

}

//找到之后,将end和start指向的元素进行交换

int temp = arr[start];

arr[start] = arr[end];

arr[end] = temp;

}

//当start和end指向了同一个元素的时候,那么上面的循环就会结束

//表示已经找到了基准数在数组中应存入的位置

//下面进行基准数归位

//就是拿着这个范围中的第一个数字,跟start(或end)指向的元素进行交换

int temp = arr[i];

arr[i] = arr[start];

arr[start] = temp;

//确定基准数左边的范围,此时左边都会比基准数小,让他们内部重复刚刚所做的事情

//i依然是0

quickSort(arr, i, start - 1);

//确定基准数右边的范围,此时右边都会比基准数大,让他们内部重复刚刚所做的事情

//j依然是len-1

quickSort(arr, start + 1, j);

}

int main() {

int arr[] = { 6,1,2,7,9,3,4,5,10,8 };

int len = sizeof(arr) / sizeof(arr[0]);

quickSort(arr, 0, len - 1);

for (int i = 0; i < len; i++) {

printf("%3d", arr[i]);

}

return 0;

}

总结

在这篇博客文章中,我详细介绍了查找算法和排序算法的各种技术和方法。希望这些内容能够帮助您更好地理解和运用算法,提升您在编程和数据处理方面的能力。如果您对这些内容有任何疑问或想要进一步探讨,欢迎在评论区留言,我会尽力解答您的问题。感谢您的阅读!

参考文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。