顺序表:删除相同元素O(n),(就地)逆置顺序表,建立顺序表【C语言,数据结构】(内含源代码)

目录

实验题目:

题目分析:

思路解析:

删除相同元素:

逆置顺序表:

源代码:

 总结:


实验题目:

设计并验证以下算法:设顺序表L中的数据元素为整数且非递增有序,删除其值相同的多余元素,即顺序表L中相同元素只保留一个,并逆置删除后的顺序表L。

1.根据键盘输入数据建立顺序表L。

2.输出顺序表L,删除之相同多余元素后的顺序表L,逆置的顺序表L。

3.假设顺序表的长度是n,要求以O(n)的时间复杂度完成对值相同多余元素的删除

题目分析:

1.根据输入建立顺序表。不需要判断是否有序,输入元素已经非递增有序了

2.删除多余元素。

3.逆置顺序表。

4.需要注意的是,所有操作都要求在原来的表里进行。

思路解析:

删除相同元素:

因为是顺序表,他的增加和删除操作没有链表那么容易,因为他的节点是不可以删的,只能删改节点里的内容。

也就是说每增加一个内容,那么要把该内容后面的内容都往后移动。

ea26c233a65c40dd90350bfc197aee95.gif

也就是说每删去一个内容,要把后面的内容都往前挪,来填充删去后的空白。

d475f0c3887c44d1be8499623e449206.gif

但值得庆幸的是,这个移动操作,是属于顺序表的基本操作,不需要我们去写。

我在这里说,是想提醒,顺序表的增删操作的对时间复杂度的影响。毕竟每次移动所有元素,耗时还是不小的。

逆置顺序表:

这个操作就比较简单了,用i指着前面的元素,用j指着后面的元素,不停交换就行。

源代码:

#include <stdio.h> 			//头文件
#include <stdlib.h>
#include <malloc.h>
#include <conio.h>
#define ERROR 0 			//函数结果状态代码
#define OK 1
#define EQUAL 1
#define OVERFLOW -1
#define LIST_INIT_SIZE 100	//顺序表存储空间的初始分配量
#define LISTINCREMENT 10	//顺序表存储空间的分配增量

typedef int Status;			//Status为函数返回值类型,其值为函数结果状态代码
 
struct NUMBER {
	int number;
};
typedef struct NUMBER ElemType;//顺序表中数据元素类型

struct LIST {
	ElemType *elem;			//顺序表的存储空间基址
	int length;				//当前长度
	int listsize;			//当前分配的存储容量
};
typedef struct LIST SqList;	//线性表的顺序存储结构定义

Status InitList_SqList(SqList *);	//构造一张新的顺序表L
Status ListInsert_SqList(SqList *, int, ElemType );	//在顺序表L的第i个元素前插入新元素e
Status DeleteSameElem(SqList *Lr);	//删除顺序表中重复元素,并用Lr返回结果
Status ReverseSqList(SqList *Lr);		//逆转顺序表,并用Lr返回结果
int ListLength_SqList(SqList);		//求顺序表L的长度
Status Destroy_SqList(SqList *);		//销毁一张顺序表
void printlist_SqList(SqList);		//输出顺序表

void input(SqList *);	//输入操作

//****main****
int main() {
	SqList La;
	
	InitList_SqList(&La);
	
	input(&La);					//根据输入创建La

	printf("Original SqList: ");
	printlist_SqList(La);		//输出原顺序表

	DeleteSameElem(&La);	//把删除重复元素后的顺序表写入La中
	printf("\nDeduplicated SqList: ");
	printlist_SqList(La);		//输出去重后的顺序表

	ReverseSqList(&La);		//把逆转元素后的顺序表写入La中
	printf("\nReversed SqList: ");
	printlist_SqList(La);		//输出逆转后的顺序表
	
	return 0;
}//main

void input(SqList *La){	//输入操作
	int l;		//用户想要创建的列表长度
	ElemType e;
	printf("How long a sequence list do you want to create?\n");
	scanf("%d",&l);
	printf("Please enter some integers to fill the sequence List:\n");

	for(int i = 1; i<=l; i++) {	//挨个把用户输入存入顺序表
		scanf("%d",&e.number);
		ListInsert_SqList(La,i,e);
	}
}	//input

Status InitList_SqList(SqList *L) {	//构造一个空顺序表L
	L->elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));//分配内存
	if(!L->elem)
		exit(OVERFLOW);
	L->length = 0;
	L->listsize = LIST_INIT_SIZE;
	return OK;
}	//InitList_SqList

Status ListInsert_SqList(SqList *L, int i, ElemType e) {	//在顺序表L的第i个元素前插入新元素e
	ElemType *newbase, *p, *q;
	if(i<1 || i>L->length+1)
		return ERROR;				//插入位置不合法
	if(L->length >= L->listsize) {	//当前存储空间已满,增加分配
		newbase = (ElemType *)realloc(L->elem, (L->listsize + LISTINCREMENT)*sizeof(ElemType));
		if(!newbase)
			return ERROR;			//存储分配失败
		L->elem = newbase;			//新基址
		L->listsize += LISTINCREMENT;	//增加存储容量
	}
	q = &(L->elem[i-1]);			//q指向插入位置
	for(p = &L->elem[L->length - 1]; p>=q; --p)
		*(p+1) = *p;				//插入位置之后的数据元素右移
	*q = e;							//插入e
	L->length++;
	return OK;
}	//ListInsert_SqList

Status DeleteSameElem(SqList *L) {	//删除顺序表中重复元素
	int i=0,j=1;
	while(j<L->length){
		if(L->elem[i].number != L->elem[j].number){	//如果不同,则把不同的送往前面
			i++;
			L->elem[i] = L->elem[j];
		}
		j++;
	}
	L->length = i+1;
	return OK;
}	//DeleteSameElem

Status ReverseSqList(SqList *L) {		//逆转顺序表
	int i,j;
	ElemType t;
	for(i = 0,j = L->length-1; i<j; i++,j--) { //顺序表从后往前遍历,前后交换
		t = L->elem[i];
		L->elem[i] = L->elem[j];
		L->elem[j] = t;
	}
	return OK;
}	//ReverseSqList

int ListLength_SqList(SqList L) {	//求顺序表L的长度
	return L.length;
}	//ListLength_SqList;

Status Destroy_SqList(SqList *L) {	//销毁一张顺序表
	free(L);
	return OK;
}	//Destroy_SqList

void printlist_SqList(SqList L) {	//输出顺序表
	int i;
	for(i = 0; i<L.length; i++)
		printf("%d ", L.elem[i].number);
	printf("\n");
}	//printlist_SqList;

 总结:

这道题是最基础的题,算是数据结构入门吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值