【数据结构C语言】顺序表基础与常用操作函数

顺序表是数据结构中最基础的数据存储方式,顺序表基本操作如下:

#include <stdio.h>
#include <malloc.h>

#define INITSIZE 100

typedef int ElemType;	//定义一种数据类型为所需,以产生不同数据类型的良好移植性
typedef struct 	//定义结构体---内容:自定义数据类型的一维数组;存入数据的长度;开辟的数组初始长度
{
	ElemType *data;
	int length;
	int listsize;
}sqlist;

void initlist(sqlist *L)	//初始化顺序表
{
	L->data = (ElemType *)malloc(sizeof(ElemType)*INITSIZE);
	L->length = 0;
	L->listsize = INITSIZE;
}
求长函数:返回顺序表实际长度:
int getlen(sqlist *L)	
{
	return(L->length);
}
取值函数:取顺序表所需位置的值写入定义好的变量地址中:
int getelem(sqlist *L,int i,ElemType *e)	
{
	if(i<1||i>L->length)
		return 0;
	*e = L->data[i-1];
	return 1;
}
定位函数:返回所查找元素的实际位置:
int locate(sqlist *L,ElemType x)	//返回所查找元素的实际位置
{
	int i = 0;
	while(i<L->length)
		if(L->data[i]==x)
			return i+1;	//可用return i;返回下标位置
		else i++;
	return 0;
}
插入函数:向指定位置插入一个指定的数:
int insert(sqlist *L,int i,ElemType x)	//插入方法
{
	int j;
	if(i<1||i>L->length+1)	//判断位置是否合理
		return 0;
	if(L->length==L->listsize)	//判断顺序表是否已满,若满了,开辟附加空间
	{
		L->data = (ElemType *)realloc(L->data,(L->listsize+1)*sizeof(ElemType));
		L->listsize++;
	}
	for(j=L->length-1;j>=i-1;j--)	//插入的核心算法
		L->data[j+1]=L->data[j];
	L->data[i-1] = x;
	L->length++;
	return 1;
}
删除函数:指定位置的元素删除,并将被删除元素写入预备好的地址中:
int Delete(sqlist *L,int i,ElemType *e)	//删除方法
{
	int j;
	if(i<1||i>L->length)
		return 0;
	*e = L->data[i-1];	//把删除了的数存在已知变量中
	for(j=i;j<L->length;j++)	//删除核心算法
		L->data[j-1] = L->data[j];
	L->length--;
	return 1;
}
快速排序函数:
void HoareSort(sqlist *L,int low,int high)
{
    int i, j, temp;
    if(low<high)
    {
        i = low;
        j = high;
        temp = L->data[i];  //以首元素作为参照物
        while(i<j)          //此while循环确定了参照元素的正确位置      
        {
            while(i<j && L->data[j]>=temp)  //此while循环找到所有【比此参照元素小的元素】
                j--;                        //将它们替换到后面
            L->data[i] = L->data[j];

            while(i<j && L->data[i]<temp)   //此while循环找到所有【比此参照元素大的或相等的元素】
                i++;                        //将它们替换到前面
            L->data[j] = L->data[i];
        }
        L->data[i] = temp;        //此时将参照元素写入正确位置【i,j共同的指向】,同时它也成为了整个待排序的顺序表的分界点
        HoareSort(L,low,i-1);     //从头到分界点的前一个元素看作一个新的待排序顺序表,继续进行上述的确定参照元素位置的操作
        HoareSort(L,i+1,high);    //从分界点末尾元素看作一个新的待排序顺序表,继续进行上述的确定参照元素位置的操作
    }   
}       //经验:如果参照元素碰巧是顺序表的【最大值】、【最小值】、【次大值】、【次小值】
        //本函数中的两个递归中,能按部就班执行的只可能有一个【因为函数的主体由“if(i<j)”来控制是否执行】
        //这在一定程度上节约了程序运行的时间,也体现出合理选择参照元素的重要性

void QuickSort(sqlist *L)
{
    HoareSort(L,0,L->length-1);
}
二表合并函数:二个递增表合并并保持递增:
void merge(sqlist *L1, sqlist *L2, sqlist *L)		//两个递增顺序表合并并保持递增
{
	int i = 0, j = 0;
	initlist(L);	//初始化顺序表
	while(i<L1->length && j<L2->length)	//i和j先指向两个顺序表的开头,循环比较,由小到大写入新的顺序表,被写入新顺序表的元素对应指针下跳,再继续比较。
		if(L1->data[i]<L2->data[j])
		{
			insert(L,L->length+1,L1->data[i]);
			i++;
		}
		else
		{
			insert(L,L->length+1,L2->data[j]);
			j++;
		}
//上一个循环退出时判断哪一个顺序表还有剩余元素未写入,用循环+插入单元素的方法将此些剩余元素写入顺序总表		
	while(i<L1->length)
	{
		insert(L,L->length+1,L1->data[i]);
		i++;
	}
	while(j<L2->length)
	{
		insert(L,L->length+1,L1->data[i]);
		j++;
	}
}
移动函数:将全表的奇数移到偶数前:
void remove(sqlist *L)		//奇数移到偶数之前操作
{
	int i = 0, L->length-1;
	ElemType temp;
	while(i<j)
	{
		while(i<j && L->data[i]%2!=0)	//从头到尾,找到奇数下跳,停在第一个偶数的位置
			i++;
		while(i<j && L->data[j]%2==0)	//从尾到头,找到偶数下跳,停在第一个奇数的位置
			j--;
		if(i<j)		//如果没有相遇,就奇偶交换
		{
			temp = L->data[i];
			L->data[i] = L->data[j];
			L->data[j] = temp;
			i++;
			j--;
		}
	}
}
输出函数:
void list(sqlist *L)	//输出顺序表
{
	int i;
	for(i = 0;i<L->length;i++)
		printf("%-3d",L->data[i]);
	printf("\n");
}
查找最值函数:
void LookForPole(sqlist *L,int *max,int *min)	//查找最值方法
{
	*max = *min = L->data[0];
	for (int i = 0;i<L->length;i++)
	{
		if(L->data[i]>*max)
			*max = L->data[i];
		else if(L->data[i]<*min)
			*min = L->data[i];
	}
}
主函数调试(插入删除与取最值):
int main()
{
	sqlist L;
	ElemType e ;
	int i,j,k,m,n,max,min;
	initlist(&L);
	printf("你想要多长的数组?");
	scanf("%d",&j);
	L.length = j;
	printf("你想在哪个地方删除或插入?");
	scanf("%d",&k);
	printf("你想要插入还是删除(插入1,删除2)");
	scanf("%d",&m);
	printf("输入%d个数",j);
	for(i=0;i<L.length;i++)
		scanf("%d",&L.data[i]);
	if(m==1)
	{
		printf("你想要插入什么数?");
		scanf("%d",&n);
		e = n;
		if(insert(&L,k,e))
			list(&L);
	}
	else
	{
		if(Delete(&L,k,&e))
			list(&L);
	}
	LookForPole(&L,&max,&min);
	printf("最大值是%d,最小值是%d\n",max,min);
	return 0;
}

主函数调试(快速排序):
int main()
{
    sqlist L;
    int j;
    initlist(&L);
    printf("你想要多长的数组?");
    scanf("%d",&j);
    L.length = j;
    printf("请输入%d个数以使顺序表完整:",j);
    for(int i=0;i<L.length;i++)
        scanf("%d",&L.data[i]);
    QuickSort(&L);
    list(&L);
    return 0;
}
本文特色:涵盖了学习链表式顺序表前必须掌握的以普通结构体为载体的顺序表的几乎所有常用操作,对每一个函数积函数的重要核心算法进行了逐句的注释详解。

部分代码来源:秦玉平《数据结构(C语言版)》,并在其基础上做了严格的C语言改进与详细的注释,并添加了书本中未曾提到的更多顺序表操作函数。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值