【头歌】第2关:实现单链表各种基本运算的算法 | 数据结构与算法(C语言)

【头歌】第2关:实现单链表各种基本运算的算法 | 数据结构与算法(C语言)

    • 任务描述
    • 目的: 领会单链表存储结构和掌握单链表中各种基本运算算法设计。
    • 内容: 实现单链表的各种基本运算(假设单链表的元素类型ElemType为char),并在此基础上设计一个程序,完成如下功能:
    • 编程要求
    • 测试说明
    • 输入样例:
    • 输出样例:
    • 完整代码

【头歌】第2关:实现单链表各种基本运算的算法 | 数据结构与算法(C语言)_第1张图片

任务描述

本关任务:实现单链表各种基本运算的算法。

目的: 领会单链表存储结构和掌握单链表中各种基本运算算法设计。

内容: 实现单链表的各种基本运算(假设单链表的元素类型ElemType为char),并在此基础上设计一个程序,完成如下功能:

(1)初始化单链表h。
(2)依次采用尾插法插入a、b、c、d、e元素。
(3)输出单链表h。
(4)输出单链表h长度。
(5)判断单链表h是否为空。
(6)输出单链表h的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素位置上插入f元素。
(9)输出单链表h。
(10)删除单链表h的第3个元素。
(11)输出单链表h。
(12)释放单链表h。

编程要求

根据提示,在右侧编辑器Begin…End之间补充代码,实现单链表基本运算算法。

测试说明

平台会对你编写的代码进行测试:

输入样例:

参见题目功能说明。

输出样例:

参见题目功能说明。
整体输出单链表表时,每个数据后面一个空格。

单链表的基本运算如下:

  (1)初始化单链表h
  (2)依次采用尾插法插入a,b,c,d,e元素
  (3)输出单链表h:a b c d e 
  (4)单链表h长度:5
  (5)单链表h为非空
  (6)单链表h的第3个元素:c
  (7)元素a的位置:1
  (8)在第4个元素位置上插入f元素
  (9)输出单链表h:a b c f d e 
  (10)删除h的第3个元素
  (11)输出单链表h:a b f d e 
  (12)释放单链表h

【头歌】第2关:实现单链表各种基本运算的算法 | 数据结构与算法(C语言)_第2张图片

完整代码

//单链表运算算法
#include 
#include 

typedef char ElemType;

typedef struct LNode {
	ElemType data;
	struct LNode *next;		//指向后继结点
} LinkNode;		 			//单链表结点类型

/**
 * 头插法建立单链表
 */
void CreateListF(LinkNode *&L, ElemType a[], int n);

/**
 * 尾插法建立单链表
 */
void CreateListR(LinkNode *&L, ElemType a[], int n);

/**
 * 初始化线性表
 */
void InitList(LinkNode *&L);

/**
 * 销毁线性表
 */
void DestroyList(LinkNode *&L);

/**
 * 判线性表是否为空表。空表返回true,否则返回false。
 */
bool ListEmpty(LinkNode *L);

/**
 * 求线性表的长度
 */
int ListLength(LinkNode *L);

/**
 * 输出线性表: 每个数据后面一个空格
 */
void DispList(LinkNode *L);

/**
 * 求线性表中第i个元素值。
 * 存在第i个数据结点,其值存入e,然后返回true。
 * 不存在第i个数据结点,返回false。
 */
bool GetElem(LinkNode *L, int i, ElemType &e);

/**
 * 查找第一个值域为e的元素序号。
 * 若存在,返回其逻辑序号;若不存在,返回0。
 */
int LocateElem(LinkNode *L, ElemType e);

/**
 * 插入第i个元素。
 * 插入成功,返回true;插入不成功,返回false。
 */
bool ListInsert(LinkNode *&L, int i, ElemType e);

/**
 * 删除第i个元素。
 * 如果第i个元素存在,其值存入e,返回true;
 * 如果第i个元素不存在,返回false。
 */
bool ListDelete(LinkNode *&L, int i, ElemType &e) ;

int main() {
	LinkNode *h;
	ElemType e;
	printf("单链表的基本运算如下:\n");
	printf("  (1)初始化单链表h\n");
	InitList(h);
	printf("  (2)依次采用尾插法插入a,b,c,d,e元素\n");
	ListInsert(h, 1, 'a');
	ListInsert(h, 2, 'b');
	ListInsert(h, 3, 'c');
	ListInsert(h, 4, 'd');
	ListInsert(h, 5, 'e');
	printf("  (3)输出单链表h:");
	DispList(h);
	printf("  (4)单链表h长度:%d\n", ListLength(h));
	printf("  (5)单链表h为%s\n", (ListEmpty(h) ? "空" : "非空"));
	GetElem(h, 3, e);
	printf("  (6)单链表h的第3个元素:%c\n", e);
	printf("  (7)元素a的位置:%d\n", LocateElem(h, 'a'));
	printf("  (8)在第4个元素位置上插入f元素\n");
	ListInsert(h, 4, 'f');
	printf("  (9)输出单链表h:");
	DispList(h);
	printf("  (10)删除h的第3个元素\n");
	ListDelete(h, 3, e);
	printf("  (11)输出单链表h:");
	DispList(h);
	printf("  (12)释放单链表h\n");
	DestroyList(h);
	return 0;
}

/* 请在下面编写程序代码 */

/**
 * 头插法建立单链表
 */
void CreateListF(LinkNode *&L, ElemType a[], int n) {
	/**************************Begin***************************/
    LinkNode *s;
    L = (LinkNode *)malloc(sizeof(LinkNode));  //为链表L分配内存空间,创建头结点
    L->next = NULL;   // 先将指向的地址为空,相当于头指针为空
    // 对数组处理
    for(int i=0; i<n; i++) {
        s = (LinkNode *)malloc(sizeof(LinkNode));  //为链表s分配内存空间
        s->data = a[i];   // 存入数据
        s->next = L->next;   // 指向下一节点
        L->next = s;  // 指向s
    }

	/***************************End****************************/
}

/**
 * 尾插法建立单链表
 */
void CreateListR(LinkNode *&L, ElemType a[], int n) {
	/**************************Begin***************************/
    LinkNode *s, *r;
    r = NULL;   
    for(int i=0; i<n; i++) {
        s = (LinkNode *)malloc(sizeof(LinkNode));
        s->data = a[i];
        s->next = NULL;

        if(r==NULL) {
            L = s;
            r = s;
        }else{
            r->next = s;
            r = s;
        }
    }
    r->next = NULL;
    
    /***************************End****************************/
}

/**
 * 初始化线性表
 */
void InitList(LinkNode *&L) {
	L = (LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
	L->next = NULL;				//单链表置为空表
}

/**
 * 销毁线性表
 */
void DestroyList(LinkNode *&L) {
	LinkNode *pre = L, *p;
	while (p != NULL) {
        p = pre->next;
		free(pre);
		pre = p;				
	}
	L = NULL;
}

/**
 * 判线性表是否为空表。空表返回true,否则返回false。
 */
bool ListEmpty(LinkNode *L) {
    /**************************Begin***************************/
	return (L == NULL);

    /**************************End***************************/
}

/**
 * 求线性表的长度
 */
int ListLength(LinkNode *L) {
	/**************************Begin***************************/
    int i;
    LinkNode *p = L;  // p指向头节点
    for(i=0; p->next != NULL; i++) {
        p = p->next;
    }
    return i;

	/***************************End****************************/
}

/**
 * 输出线性表: 每个数据后面一个空格
 */
void DispList(LinkNode *L) {
	/**************************Begin***************************/    
    LinkNode *p = L;	//p指向首结点
    while (p != NULL&&p->next!=NULL) {		//p不为NULL,输出p结点的data域       
        printf("%c ", p->data);
        p = p->next;			//p移向下一个结点
    }
    printf("\n");
    /***************************End****************************/
}

/**
 * 求线性表中第i个元素值。
 * 存在第i个数据结点,其值存入e,然后返回true。
 * 不存在第i个数据结点,返回false。
 */
bool GetElem(LinkNode *L, int i, ElemType &e) {
	/**************************Begin***************************/
    LinkNode *p=L;  // 从头开始遍历
    int count = 0;  // 用于计数当前遍历到的结点序号
    while (p != NULL) {
        count++;
        if (count == i) {   // 如果当前结点序号等于i,则将该结点的数据域值存入e中
            e = p->data;
            return true;
        }
        p = p->next;
        
    }
    return false;  // 遍历完整个链表仍然没有找到第i个元素,返回false
    
    /***************************End****************************/
}

/**
 * 查找第一个值域为e的元素序号。
 * 若存在,返回其逻辑序号;若不存在,返回0。
 */
int LocateElem(LinkNode *L, ElemType e) {
	/**************************Begin***************************/
    int count = 1;
    while (L != NULL) {
        if(L->data == e) {
            return count;
        }
        L = L->next;
        count++;
    }
    return 0;
    
	/***************************End****************************/
}

/**
 * 插入第i个元素。
 * 插入成功,返回true;插入不成功,返回false。
 */
bool ListInsert(LinkNode *&L, int i, ElemType e) {
	/**************************Begin***************************/
    if(i<1 || L==NULL) {
        return false;
    }
    
    LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
    s->data = e;
    s->next = NULL;

    if(i==1) {  // 如果插入到头部
        s->next = L;
        L = s;
    } else {  // 如果插入到中间或尾部
        LinkNode *p = L;  // 当前指针结点
        int count = 1;
        while(p!=NULL&&count<i-1) {
            p = p->next;
            count++;
        }
        if(p == NULL) {
            return false; // 到达链表尾部,无法插入
        }
        s->next = p->next;
        p->next = s;
    }
    return true;  // 成功插入返回true

	/***************************End****************************/
}

/**
 * 删除第i个元素。
 * 如果第i个元素存在,其值存入e,返回true;
 * 如果第i个元素不存在,返回false。
 */
bool ListDelete(LinkNode *&L, int i, ElemType &e) {
	/**************************Begin***************************/
    if(L==NULL || i<1) {
        return false;
    }

    int count = 1;
    LinkNode *p = L;

    while(p!=NULL && count<i-1) {   //【1】
        p = p->next;
        count++;
    }

    if(p==NULL) {
        return false;
    }
    
    e = p->data;
    LinkNode *q = p->next;
    p->next = q->next;
    free(q);

    return true;

	/***************************End****************************/
}

注意: 删除第i个元素bool ListDelete(LinkNode *&L, int i, ElemType &e)中, while(p!=NULL && count

当count等于i-1时,p指针就指向了第i个元素的前一个节点。然后,p->next就指向了第i个元素。因此,你可以通过p->data来获取第i个元素的值。

当我们通过p指针访问链表中的某个节点时,p指向的是第i-1个节点,而p->data则是获取第i个节点的数据。因为链表的第一个节点索引为0,所以当我们说第i个元素时,实际上是指的第i-1个节点中的数据。

例如,如果有一个链表,它的头节点是head,那么head->data就是链表中的第一个元素,head->next->data就是第二个元素,head->next->next->data就是第三个元素,以此类推。所以当我说第i个元素时,实际上是指的是第i-1个节点中的数据。

你可能感兴趣的:(数据结构(C语言),算法,c语言,开发语言)