10.7 顺序表功能拓展

排序

冒泡排序

基本原理(相邻元素比较交换)

从头到尾遍历数组,比较两个相邻的的元素,若前一个大于后一个则交换

一轮遍历后,最大的元素会冒泡到数组的末尾

重复以上步骤至排序完成

特点

时间复杂度:O(n²)

稳定,相同元素的相对顺序不会改变

代码示例

void bubbleSort(ElemType arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换
                ElemType temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

选择排序

基本原理(查找最大/小再交换)

在未排序的部分中找到最小(或最大)元素,将它与未排序部分的第一个元素进行交换

每次将一个元素放到最终位置,直至排序完成

特点

时间复杂度:O(n²)

不稳定,可能改变相同元素的相对位置

代码示例

void selectionSort(ElemType arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int minIndex = i;  // 假设当前位置是最小值
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;  // 找到新的最小值索引
            }
        }
        // 交换
        if (minIndex != i) {
            ElemType temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }
}

运用示例(冒泡排序)

void SqList_Sort(SqList& L)
{
	for (int i = 0;i < L.length - 1;i++)
	{
		for (int j = 0;j < L.length - 1 - i;j++)
		{
			if (L.elem[j] > L.elem[j + 1])
			{
				ElemType t = L.elem[j];
				L.elem[j] = L.elem[j + 1];
				L.elem[j + 1] = t;
			}
		}
	}
}

代码解读:

(SqList& L),关于何时用&

当需要对表中内容进行改动时(如插入、删除),需要加&

不需要改动时(如查找、输出),则不需要加&

与数组的差别

与数组相比,对顺序表的排序只改动了传入参数,以及将n改为了L.length

按序插入(已排序)

代码内容:

Status SqList_Insert_In_Order(SqList& L, ElemType e)
{
    int i;
    if (L.length >= L.listsize) // 检查表是否满
        return OVERFLOW;

    // 找到插入位置
    for (i = 1; i <= L.length && L.elem[i - 1] <= e; i++);

    // i 此时指向第一个大于 e 的位置
    for (int j = L.length - 1; j >= i - 1; j--)
        L.elem[j + 1] = L.elem[j]; // 将元素向后移动
    
    L.elem[i - 1] = e; // 插入新元素
    L.length++; // 更新长度
    return OK; // 成功
}

代码逻辑

判满

遍历寻找插入位置,用计数器储存

移动元素留出空位

插入

更新长度

逆置

Status SqList_Reverse(SqList& L)
{
	int left = 0, right = L.length - 1;
	while (left < right)
	{
		int t = L.elem[left];
		L.elem[left] = L.elem[right];
		L.elem[right] = t;
		left++;
		right--;
	}
	return OK;
}

代码逻辑

对首尾使用计数器循环交换逼近

代码解读

while (left < right)

对左右(首尾)计数器进行比较,并在相撞时停止交换(交换完成)

删除重复元素

Status SqList_DeleteSame(SqList& L) 
{
	for (int i = 0; i < L.length; i++) 
	{
		for (int j = i + 1; j < L.length; ) 
		{
			// 如果发现重复元素
			if (L.elem[j] == L.elem[i]) 
			{
				// 移动元素
				for (int k = j; k < L.length - 1; k++) 
				{
					L.elem[k] = L.elem[k + 1];
				}
				// 长度减1
				L.length--;
			}
			else {
				// 只有当没有重复时才能往后走
				j++;
			}
		}
	}
	return OK;
}

代码逻辑

使用双层循环,外层推进,内层遍历删除

删除特定元素

Status SqList_Delete_X(SqList& L, ElemType X)
{
	for (int i = 0;i < L.length;)
	{
		if (L.elem[i] == X)
		{
			// 移动元素
			for (int k = i; k < L.length - 1; k++)
			{
				L.elem[k] = L.elem[k + 1];
			}
			// 长度减1
			L.length--;
		}
		else 
		{
			// 只有当没有重复时才能往后走
			i++;
		}
	}
	return OK;
}

合并线性表(有序)

Status SqList_merge(SqList& LA, SqList& LB, SqList& LC)
{
	LC.listsize = LA.listsize + LB.listsize;
	LC.elem = (ElemType*)malloc(LC.listsize * sizeof(ElemType));
	if (!LC.elem)
	{
		return OVERFLOW;
	}
	LC.length = 0;

	int i = 0, j = 0, k = 0; // i指向LC, j指向LA, k指向LB
	while (j < LA.length && k < LB.length) 
    {
		if (LA.elem[j] < LB.elem[k]) 
        {
			LC.elem[i++] = LA.elem[j++];
		}
		else 
        {
			LC.elem[i++] = LB.elem[k++];
		}
	}
	// 处理LA或LB剩余元素
	while (j < LA.length) 
    {
		LC.elem[i++] = LA.elem[j++];
	}
	while (k < LB.length) 
    {
		LC.elem[i++] = LB.elem[k++];
	}
	LC.length = i; // 更新LC长度
	return OK;
}

代码逻辑

根据两表长度决定新表大小

为新表分配内存

比较两表元素有序放入新表内

代码解读

while (j < LA.length && k < LB.length) 

使用while循环遍历LALB,直到有一个线性表遍历结束。

while (j < LA.length) 
    {
		LC.elem[i++] = LA.elem[j++];
	}
while (k < LB.length) 
    {
		LC.elem[i++] = LB.elem[k++];
	}

二者其实是或的关系,即较长的表继续将剩余元素输入进去

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值