文章目录
本文章代码全为伪代码
线性表
线性表包含顺序表和链表,链表包含单链表、循环链表、双向链表
顺序表的基本运算
插入运算
注释:
结构体成员的引用
- 箭头(->):左边必须为指针
- 点(.):左边必须为实体
// L为结构体的指针,i为在第i个位置之前插入元素,x为插入的元素
void InsertList(SeqList *L, int i, DataType x)
{
int j; // 表L最后一个元素索引位
//判断插入位置是否小于1或者大于最后一位+1
if(i<1 || i>L->length+1){
printf("position error")
return;
}
// 判断表是否已满
if(L->length>=ListSize){
printf("overflow")
return;
}
for(j=L->length-1;j>=i-1;j--){
L->data[j+1]=L->data[j]; //将i位之后元素,逐一后移
}
L->data[i-1]=x; //将x插入第i位
L->Length++; //列表长度+1
}
删除运算
//L为结构体指针,i为删除i位置的元素
viod DeleteList(SeqList *L, int i){
int j; //j为删除元素的下标
DataType x; //定义需要删除的元素
if(i<1 || i>L-Length){
printf("position error");
return;
}
// 从第i位后元素开始,依次加前移
for(j=i-1;j<=L->Length-1;j++){
L->data[j]=L->data[j+1];
}
L->Length--;
return x;
}
顺序表综合使用
试写一算法,实现在顺序表中找出最大值和最小值的元素及其所在的位置
// 使用4个变量分别记录,最大值、最小值以及最大值位置和最小值位置
void MaxMin(SeqList L, DataType *max, DataType *min, int *k, int *j)
{
int i; //i初始值为1,第0位指针元素无需判断
*max=L.data[0];
*min=L.data[0];
*k=*j=1; //初始化第一个元素为最大值和最小值
for(i=1;i<L.length;i++){
if(L.data[i]>*max){
*max=L.data[i];
*k=i;
}
else if(L.data[i]<*min){
*min=L.data[i];*j=i
}
}
}
已知一个长度为n的顺序存储的线性表,试写一算法将该线性表逆置
思路:a,b值互换,需要一个中间变量x,x=a,a=b,b=x
SeqList Converts(SeqList L)
{
DataType x; //模糊定义一个x数据类型变量,用来存储逆序时的值
int i,k; //i为顺序表的下标,k为顺序表长度的一半
k=L.length/2;
for(i=0;i<k;i++){
L.data[i]=L.data[L.length-i-1]
L.data[L.length-i-1]=x;
}
return L;
}
假设有两个线性表LA和LB分别表示两个集合A和B,现要求一个新的集合A=A∪B(集合的并)
思路:在LB中循环得出值x,判断x是否在LA中,不存在则添加到LA中
void union(Linner_List LA,Linner_List LB)
{
n=ListLength(LA);
int i; //i为LB的下标
DataType x; //模糊定义x的数据类型
for(i=0;i<=List;i++){
x=GetNode(LB,i); //获取线性表LB中下标为i的值
if(LocateNode(LA,x)==0) //获取x值在LA中的位置,若为0表示不存在
InsertList(LA,++n,x); //在LA的N+1位置插入x
}
}
删除线性表L中重复的元素
思路:从表L的第一个元素(i=1)开始,逐个检查i位置后的任意一位j,若两值相同,则从L表中移除,直到L表的最后一位为止。
void purge(Linera_List L)
{
int i,j;
DataType x,y;
i=1;
while(i<=ListLength(L)){ //注意,此处L表的长度只能动态获取,不能提前获取
x=GetNode(L,i);
j=i+1;
// 逐个判断i后每位值是否与i相同
while(j<=ListLength(L)){ //注意,此处L表的长度只能动态获取,不能提前获取
y=GetNode(L,j);
if(x==y){
DeleteList(L,j);}
else
j++;
}
}
}
单链表的基本运算
建立单链表
头插法建表
头插法建表是从一个空表开始,重复读入数据,生成新的节点,将读入的数据存放到新节点的数据域中,然后将新节点插入到当前链表的表头上,知道读入结束标志为止。
例:在空链表head中依次插入数据域分别为a、b、c的节点之后,将x为数据域的新结点p插入到当前链表表头,其指针的修改变化如下图
LinkList CreateListF()
{
LinkList head; //链表的首个元素的指针
ListNode *p; //p 为需要插入元素的指针
char ch; //需要插入的元素
head=NULL; //置空链表
ch=getchar(); //获取第一个元素(伪代码)
while(ch!='\n'){
p=(ListNode *)malloc(sizeof(ListNode)); //申请新的节点,动态扩容
p->data=ch;
p->next=head;
head=p;
ch=getchar(); //获取下一个元素
}
return head; //返回链表的头指针
}
尾插发建表
为了方便操作,引入头结点
// 尾插法建立带头结点的单链表算法
Link CreatListR()
{
LinkList head=(ListNode *)malloc(sizeof(ListNode)); // 申请头结点
ListNode *p,*r; // p 为插入元素指针,r为尾指针
DataType ch;
r=head; // 将尾指针指向头结点,此时链表为空
while((ch = getchar())!='\n'){
p=(ListNode *)malloc(sizeof(ListNode)); //申请新节点
p->data=ch;
r->next=p; // 将新添加的元素,连接到链表,插入第一个元素时,等价于head->next=p
r=p; // 将尾指针指向尾节点
}
r->next=NULL; // 循环结束后,将尾指针置空
return head; // 返回链表的头结点
}
查找运算(带头结点),返回内存地址
按节点序号查找
序号为0是头结点
// head为带头结点的单链表的头指针,i为要查找的节点序号
// 若查找成功,则返回查找节点的存储地址,否则返回NULL
ListNode * GetNodei(LinkList head, int i)
{
// 指针p为节点的指针,j为节点的序号
ListNode *p; int j;
p=head->next; j=1; // 将p指向head, j置为1
while(p&&j<i){ // 当p为NULL或循环到第j位为止
p=p->next; ++j // 将p指针指向下一个节点
}
if(j=i){
return p; // 返回查找节点的内存地址
}
else{return NULL;}
}
按节点值查找
// head 为带头结点的单链表的头指针,k为要查找的节点的值
// 查找成功返回存储节点内存地址,失败返回NULL
ListNode * LocateNodek(LinkList head, DataType k)
{
ListNode *p;
p=head->next;
while(p&&p->data!=k){ // 当p非空和值不为k时执行
p=p->next; // 指针指向下一个节点
}
return p; // 返回查找节点的内存地址
}
插入运算
void InsertNode(LinkList head, int i, DataType x)
{
ListNode *p; int j;
p=head;
j=0; //0号节点为头结点
while(p&&j<i-1){
p=p->next; // 指向下一个节点
++j;
}
if(p==NUll){
printf("error\n");return
}
else{
s=(ListNode *)malloc(sizeof(ListNode)); //申请新节点
s->data=x; // x为插入节点的数值域
s->next=p->next;
p->next=s;
}
}
删除运算
将单链表的第i个节点删除,并返回节点的值
DataType DeleteList(LinkList head,int i){
// 在以head为头指针的带头结点的单链表中删除第i个节点
ListNode *p, *s; // p为循环节点的指针,s为删除节点的指针 i-1 对应的p,i对应的s
DataType x;int j; // x为删除节点的返回值 x=s->data, j为节点位置,从0开始,0对应头结点
p=head; j=0; // p指向头结点
while(p!=NULL && j<i-1){
p=p->next; // 循环节点后移
++j;
}
if(p==NULL){
printf("位置有误\n");
exit(0);
}
else{
s=p->next; //s对应循环节点p的下一个节点
p->next=s->next;
x=s->data
free(s);
return(x)
}
}