数据结构第一轮复习--第二章线性表(包含课程作业代码)

发布于:2025-03-15 ⋅ 阅读:(12) ⋅ 点赞:(0)

线性表的顺序表示

顺序表的实现(静态分配)

#include <stdio.h>
 //静态创建一个顺序表
 #include <stdio.h>
 #define Maxsize 10
 typedef struct{
 	int data[Maxsize];
 	int length;
 }SqList;
 
//初始化一个顺序表 
void InitList(SqList &L){
	L.length = 0;
	for(int i=0;i<Maxsize;i++)
		L.data[i]=0;
}

int main(){
	SqList L;
	InitList(L);
	for(int i=0;i<Maxsize;i++)
		printf("data[%d]=%d\n",i,L.data[i]);
	return 0;
}

顺序表的实现(动态分配)

//动态创建一个顺序表
#define InitSize 10
typedef struct{
	int *data; //指示动态分配数组的指针 
	int MaxSize;
	int length;
}SeqList;

//初始化
void InitList(SeqList &L){
	//用malloc函数申请一片连续的存储空间
	L.data=(int *)malloc(InitSize*sizeof(int));
	L.length=0;
	L.MaxSize=InitSize; 
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

//增加动态数组的长度
void IncreaseSize(SeqList &L, int len){
	int *p = L.data;//p指针跟data指针指向同一个地址
	L.data = (int *)malloc((L.MaxSize+len)*sizeof(int));
	for(int i=0;i<L.length;i++){
		L.data[i]=p[i];
	} 
	L.MaxSize=L.MaxSize+len;
	free(p);
} 

int main(){
	SeqList L;
	InitList(L);
	IncreaseSize(L,5);
	return 0;
}

顺序表的基本操作--插入 

#include <stdio.h>
#include <stdlib.h>

#define MaxSize 10

typedef struct {
    int data[MaxSize]; // 存储数据
    int length;        // 顺序表长度
} SqList;

// 顺序表的基本操作--插入 :在 L 的位序 i 处插入元素 e 
bool ListInsert(SqList &L, int i, int e) {
    if (i < 1 || i > L.length + 1) // 检查 i 是否越界
        return false;
    if (L.length >= MaxSize) // 检查是否已满
        return false;

    // 插入操作
    for (int j = L.length; j >= i; j--)
        L.data[j] = L.data[j - 1];
    L.data[i - 1] = e;
    L.length++;
    return true; // 插入成功
}

// 初始化顺序表 
void InitList(SqList &L) {
    L.length = 0;
    for (int i = 0; i < MaxSize; i++)
        L.data[i] = 0;
}

int main() {
    SqList L;
    InitList(L);

    // 输出初始化数据
    for (int i = 0; i < MaxSize; i++)
        printf("data[%d]=%d\n", i, L.data[i]);

    // 插入元素
    if (ListInsert(L, 1, 3)) {
        printf("插入成功!\n");
    } else {
        printf("插入失败!\n");
    }

    // 输出插入后的数据
    for (int i = 0; i < MaxSize; i++)
        printf("data[%d]=%d\n", i, L.data[i]);

    return 0;
}

因为

for (int j = L.length; j >= i; j--)
        L.data[j] = L.data[j - 1];,说明插入操作从最后一个元素开始后移

注意:实行插入操作时,要避免当前列表是一个空列表,否则插入操作可能会失败,

因为你不能在空的顺序表里直接插入第 5 个元素,必须先插入 i=1i=2……再到 i=5

 顺序表的基本操作--删除

bool ListDelete(SqList &L, int i, int &e) {
    if (i < 1 || i > L.length) // 检查 i 是否越界
        return false;
        e=L.data[i-1];
	//删除 
    for (int j = i; j < L.length; j++)
        L.data[j-1] = L.data[j];
    L.length--;
    return true; // 插入成功
}

注意:删除操作

for (int j = i; j < L.length; j++)
        L.data[j-1] = L.data[j];说明从最前面的一个元素开始前移

顺序表的按位查找

int GetElem(SqList &L, int i) {
    if (i < 1 || i > L.length) { 
        printf("索引 %d 超出范围,当前表长: %d\n", i, L.length);
        return -1;
    }
    return L.data[i-1];
}

注意:主函数中,应该返回的是函数值,而不是函数名

正确:printf("第 1 个元素: %d\n", GetElem(L, 1)); 

错误:printf("第 1 个元素: %d\n", GetElem); 

顺序表的按值查找

//按值查找,找到顺序表L中的第一个元素值等于e的值,并返回其位序 
int LocateElem(SqList L,int e){
	for(int i=0;i<L.length;i++)
		if (L.data[i]==e)
			return i+1; //数组下标为i的元素值等于e,但位序是i+1 
	return 0;
}

顺序表作业部分:

01

我的代码:

bool Deletemin(Sqlist &L, int e){
	for (int i=0;i<=L.length;i++)
		if (L.data[i]>=L.data[i+1])
			L.data[i]=L.data[i+1];
			e=data[i];
		for (int j = i; j < L.length; j++)
			L.data[j-1] = L.data[j];
		L.length--;
	return true;
		
}

存在的问题:

正确的代码:

bool Deletemin(Sqlist &L, int &e) {
    if (L.length == 0) return false;  // 防止空表操作

    // 1. 找到最小值及其索引
    int minIndex = 0;
    for (int i = 1; i < L.length; i++) {
        if (L.data[i] < L.data[minIndex]) {
            minIndex = i;
        }
    }

    // 2. 记录最小值
    e = L.data[minIndex];

    // 3. 删除该元素,后面的元素前移
    for (int i = minIndex; i < L.length - 1; i++) {
        L.data[i] = L.data[i + 1];
    }

    // 4. 长度减少
    L.length--;

    return true;
}

02

线性表的链式表示 

单链表的代码定义

//单链表的代码定义
typedef struct LNode{   	//定义单链表的节点类型 
	ElemType data;      	//每个节点存放一个数据元素 
	struct LNode *next;		//指针指向下一个节点位置 
}LNode,*LinkList; 

单链表的初始化和判空操作

带头节点

bool InitList(LinkList &L){
	L = (LNode *)malloc(sizeof(LNode)); //创建头节点
	L->next=NULL;   //头节点之后暂时还没有节点,所以是空 
	return true; 
}

bool Empty(LinkList &L){
	if (L->next==NULL)
		return true;
	else
		return false;
}

不带头节点

bool InitList(LinkList &L){
	L = NULL;  //空表,无节点,防止脏数据设置为NULL
	return true;
}

bool Empty(LinkList &L){
	if(L==NULL)
		return true;
	else
		return false;
}

bool Empty(LinkList L){
	return (L==NULL);
}

单链表的插入操作(按位序插入)

带头节点

//在第i个位置插入元素e(带头节点)
bool ListInsert(LinkList &L,int i,ElemType e){
	if(i<1)
		return false;
	LNode *p;	//指针p指向当前扫描到的节点
	int j=0;	//当前p指向的是第几个节点 
	p = L;		//L指向头指针,头指针是第0个节点(不存数据)
	while(p!=NULL && j<i-1) {	//循环找到第i-1个节点
		p=p->next;
		j++; 
	}
	if(p==NULL)		//i值不合法
		return false;
	//用malloc函数申请新的节点空间,在空间里存放插入的数据元素和指针 
	LNode *s = (LNode *)malloc(sizeof(LNode));
	s->data = e;	//将参数e存到新节点
	s->next = p->next; //将原本i节点的后继节点,即p指针的next
	p->next=s;	//将节点s连接到p之后
	return true; //插入成功 
}

 

不带头节点

//按位序插入(不带头节点)
bool ListInsert(LinkList &L,int i,ElemType e){
	if(i<1)
		return false;
	if(i==1){	//插入第1个节点与其他节点操作不同 
		LNode *s = (LNode *)malloc(sizeof(LNode));
        if (s == NULL) return false;  // 检查内存分配
		s->data = e;
		s->next = L;//因为此时的头指针是第一个节点,所以在表头插入,需要将下一个指针指向头指针 
		L = s; //头指针指向新节点 
		return true; 
	}	
	LNode *p;
	int j=1;	//因为无头节点,所以p指针一开始就指向第一个节点,所以j=1
	p = L;		//p指针指向第1个节点,(不是头节点) 
	while(p!=NULL && j<i-1) {	//循环找到第i-1个节点
		p=p->next;
		j++; 
	}	
	if(p==NULL)		//i值不合法
		return false; 
	LNode *s = (LNode *)malloc(sizeof(LNode));
    if (s == NULL) return false;  // 检查内存分配
	s->data = e;	//将参数e存到新节点
	s->next = p->next; //将原本i节点的后继节点,即p指针的next
	p->next=s;	//将节点s连接到p之后
	return true; //插入成功 	
}

后插操作 

//后插操作:在p节点之后插入元素e
bool InsertNextNode(LNode *p,ElemType e){
	if(p==NULL) return false;
	LNode *s = (LNode *)malloc(sizeof(LNode));
	if (s == NULL) return false;
	s->data = e;	//将参数e存到新节点
	s->next = p->next; //将原本i节点的后继节点,即p指针的next
	p->next=s;	//将节点s连接到p之后
	return true; //插入成功 	
}

前插操作

//前插操作:在p节点之前插入元素e,偷梁换柱将p和s节点的数据和指针互换 
bool InsertPriorNode (LNode *p,ElemType e){
	if(p==NULL) return false;
	LNode *s = (LNode *)malloc(sizeof(LNode));
	if(s==NULL) return false;//内存空间分配失败
	s->next = p->next; //将p节点指针的指向先赋值给s节点 
	p->next = s;//将新建立的s节点连接到p之后,以便后面与s节点交换 
	s->data = p->data;//将p中元素复制到s节点中,实现交换,此时在逻辑上,s节点就是p节点 
	p->data = e;//将原先的p节点数据更换为e,就是将p节点变换成实际的新插入的节点 
	return true;
}

单链表的删除操作 

按位序删除(带头节点)

//按位序删除(带头节点)
bool ListDelete(LinkList &L,int i,ElemType &e){
	if(i<1) return false;
	LNode *p;	//指针p指向当前扫描到的节点
	int j=0;	//当前p指向的是第几个节点 
	p = L;		//L指向头指针,头指针是第0个节点(不存数据)
	while(p!=NULL && j<i-1) {	//循环找到第i-1个节点
		p=p->next;
		j++; 
	}
	if(p==NULL)		//i值不合法
		return false;
	if(p->next == NULL)//第i个节点之后已经没有其他节点
	LNode *q = p->next; //让q指向要被删除的节点
	e = q->data;		//用e返回元素的值 
	p->next = q->next; //将*q节点从链中“断开”
	free(q);
	return true; 
	
}

指定节点的删除

p 的后继节点的数据复制到 p,然后删除后继节点

//删除指定节点p
bool DeleteNode(LNode *p){
	if(p==NULL) return false;
	LNode *q = p->next; //令q指向*p的后继节点 
	p->data = p->next->data; // 和后继节点交换数据域
	p->next = q->next; //将*q结点从链中‘断开’
	free(q);
	return true; 
} 

 

bool DeleteNode(LNode *p) {
    if (p == NULL) {
        // 如果p为空,无法删除
        return false;
    }

    if (p->next == NULL) {
        // 如果p是最后一个节点,无法使用这种方法删除
        // 因为没有后继节点可以复制数据
        return false;
    }

    // 令q指向p的后继节点
    LNode *q = p->next;

    // 将后继节点的数据复制到p
    p->data = q->data;

    // 将q节点从链中“断开”
    p->next = q->next;

    // 释放q节点的内存
    free(q);

    return true;
}

单链表的按位查找(带头节点)

LNode *GetElem(LinkList L,int i){
	if(i<0) return NULL;
	LNode *p;	//指针p指向当前扫描到的节点
	int j=0;	//当前p指向的是第几个节点 
	p = L;		//L指向头指针,头指针是第0个节点(不存数据)
	while(p!=NULL && j<i) {	//循环找到第i个节点
		p=p->next;
		j++; 
	}
	return p;
} 

单链表的按值查找(带头节点)

//单链表的按值查找,找到数据域==e的结点 
LNode * LocateElem(LinkList L,ElemType e){
	//从第一个节点开始查找数据域为e的节点 
	LNode *p = L->next;
	while(p!=NULL && p->data!=e)
		p=p->next;
	return p; //找到后返回该结点指针,否则返回NULL 
} 

尾插法建立单链表

//尾插法建立单链表
LinkList_TailInsert(LinkList &L){	//正向建立单链表
	int x;							//设ElemType为整形 
	L=(LinkList)malloc(sizeof(LNode));//建立头节点,初始化空表 
	//r为表尾指针,s是要新插入的结点指针,此时都指向L(头指针) 
	LNode *s,*r=L;				
	scanf("%d",&x);
	while(x!=9999){
		s=(LNode*)malloc(sizeof(LNode));
		s->data=x;
		//在r结点之后插入元素x 
		r->next=s;
		r=s; 	//永远保持r指向新的表尾结点 
		scanf("%d",&x);
	} 
	r->next=NULL;//表尾指针置空 
	return L; 
} 

头插法建立单链表

//头插法建立单链表
LinkList List_HeadInsert(LinkList &L){//逆向建立单链表
	LNode *s; 
	int x;							//设ElemType为整形 
	L=(LinkList)malloc(sizeof(LNode));//建立头节点
	L->next=NULL;		//初始化为空列表 
	scanf("%d",&x);		//输入结点的值 
	while(x!=9999){
		s=(LNode*)malloc(sizeof(LNode));//创建新结点 
		s->data=x;
		s->next=L->next;
		L->next=s; //将新节点插入表中,L为头指针 
		scanf("%d",&x);
	} 
	return L;
}

双链表

//用代码定义一个双链表
typedef struct DNode{
	ElemType data;
	struct DNode *prior,*next;
}; DNode,*DLinklist;

 初始化和判空操作

//初始化双链表
bool InitDLinklist(DLinklist &L){
	L = (DNode *)malloc(sizeof(DNode))//分配一个头结点
	if(L==NULL)
		return false;
	L->prior = NULL;
	L->next = NULL;
	return true;
}
//判空操作
bool Empty(DLinklist L){
	if(L->next == NULL)
		return true;
	else 
		return false;
} 

插入操作(后插)

bool InsertNextDNode(DNode *p, DNode *s){
	if(p==NULL||s==NULL)
		return false;
	s->next=p->next;
	s->prior=p;
	if (p->next!=NULL)
		p->next->prior=s;
	p->next=s;
	return true;
} 

双链表的删除

//删除p的后继结点q
bool DeleteNextDNode(DNode *p){
	if (p==NULL) return false;
	DNode *q = p->next;//找到后继结点q
	if (q==NULL) return false;//p没有后继 
	p->next=q->next;
	if(q->next!=NULL)
		q->next->prior=p;
	free(q); //释放结点空间 
	return true;
}

循环链表

循环单链表

//循环单链表的初始化和判空
bool InitList(LinkList &L){
	L = (LNode *)malloc(sizeof(LNode)); //创建头节点
	if (L==NULL) return false;
	L->next=L;   //头节点next指向头结点 
	return true; 
}
//判断结点p是否为循环单链表的表尾结点 
bool Empty(LinkList &L,LNode *p){
	if (p->next==L)
		return true;
	else
		return false;
}

 循环双链表

//初始化循环双链表
bool InitDLinklist(DLinklist &L){
	L = (DNode *)malloc(sizeof(DNode))//分配一个头结点
	if(L==NULL)
		return false;
	L->prior = L;//头结点的prior指向头结点 
	L->next = L;//头结点的next指向头结点 
	return true;
}
//判空操作
bool Empty(DLinklist L){
	if(L->next == L)
		return true;
	else 
		return false;
}  
//判断结点p是否为循环双链表的表尾结点
bool isTail(DLinklist L,DNode *p){
	if(p->next==L)
		return true;
	else
		return false;
} 


网站公告

今日签到

点亮在社区的每一天
去签到