目录
实验题目:
设计并验证以下算法:设顺序表L中的数据元素为整数且非递增有序,删除其值相同的多余元素,即顺序表L中相同元素只保留一个,并逆置删除后的顺序表L。
1.根据键盘输入数据建立顺序表L。
2.输出顺序表L,删除之相同多余元素后的顺序表L,逆置的顺序表L。
3.假设顺序表的长度是n,要求以O(n)的时间复杂度完成对值相同多余元素的删除
题目分析:
1.根据输入建立顺序表。不需要判断是否有序,输入元素已经非递增有序了
2.删除多余元素。
3.逆置顺序表。
4.需要注意的是,所有操作都要求在原来的表里进行。
思路解析:
删除相同元素:
因为是顺序表,他的增加和删除操作没有链表那么容易,因为他的节点是不可以删的,只能删改节点里的内容。
也就是说每增加一个内容,那么要把该内容后面的内容都往后移动。
也就是说每删去一个内容,要把后面的内容都往前挪,来填充删去后的空白。
但值得庆幸的是,这个移动操作,是属于顺序表的基本操作,不需要我们去写。
我在这里说,是想提醒,顺序表的增删操作的对时间复杂度的影响。毕竟每次移动所有元素,耗时还是不小的。
逆置顺序表:
这个操作就比较简单了,用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;
总结:
这道题是最基础的题,算是数据结构入门吧。