数据结构c语言——链表

1.链表定义

链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表
中的指针链接次序实现的 。

链表里的的每节"⻋厢"都是独⽴申请下来的空间,我们称之为“结点/节点”。

节点的组成主要有两个部分:(数据域)当前节点要保存的数据和(指针域)保存下⼀个节点的地址(指针变量)。

链表中每个节点都是独⽴申请的(即需要插⼊数据时才去申请⼀块节点的空间),我们需要通过指针 变量来保存下⼀个节点位置才能从当前节点找到下⼀个节点。
链表分为:单链表、双向链表、循环链表。

2.功能实现

单链表定义

//定义结点的结构体
typedf struct LNode{   //定义单链表结点类型
  ElemType data ;      //每个结点存放一个数据元素
  struct LNode *next;  //指针指向下一个结点

}LNode;

//定义链表的结构体
typedef struct LinkList{
  struct ListNode* head;   //定义头结点
  int size;                //定义链表大小
}LinkList;

单链表初始化和销毁

void LinkListCreat(LinkList* list){
list.head=NULL;
list.size=0;

}
void LinkListDestory(LinkList* list){
while(list.head){
   ListNode* temp=list->head;   //将链表头储存在临时变量中
   list->head= list->haed->next;   //改变当前头结点 使其成为后继
   free(temp);
}//遍历完即销毁完成
list->size=0;
}

单链表查询

(定义新指针p,H结构体的指针域赋值给p,判断不为空且数据域不是目标,后移,返回值)

int Get_LinkList(LinkList H, ElemType key) {
    LNode* p = H->next;
    int pos = 1;
    while (p != NULL && p->data != key) {
        p = p->next;
        pos++;
    }
    if (p == NULL) {
        return 0; // 未找到
    } else {
        return pos; // 返回位置
    }
}

单链表插入

(和结构体关联 判断合法即后移,遍历到插入位置的前一个元素, 为新元素申请空间 赋值 p的next给新元素next 新元素赋值给p的next)

Status ListInsert(LinkList &H, int i, ElemType e) {
    LNode* p = H;
    int j = 0;
    while (p != NULL && j < i - 1) {
        p = p->next;
        j++;
    }
    if (p == NULL || j > i - 1) {
        return ERROR; // 插入位置不合法
    }
    LNode* newNode = (LNode*)malloc(sizeof(LNode));
    newNode->data = e;
    newNode->next = p->next;
    p->next = newNode;
    return OK;
}

一定要先把原本结点的指针域赋值给新元素,否则后续元素可能会丢失

若插入位置是0,则直接把生成的节点的后续节点,设置为当前链表的头结点,并把生成的节点设置为新链表头

if(i==0){
  newNode->data=list->head;
  list->head=newNode;
}

最后更新链表大小,即对链表的长度进行+1操作

单链表删除

(和结构体关联 判断合法即后移,遍历到删除位置的前一个位置, 创建新指针 p的next 赋值给q q的next再给p的next(把前一个结点的后继结点设置为后继的后继) 释放q)

Status ListDelete(LinkList &H, int i) {
    LNode* p = H;
    int j = 0;
    while (p != NULL && j < i - 1) {
        p = p->next;
        j++;
    }
    if (p == NULL || p->next == NULL || j > i - 1) {
        return ERROR; // 删除位置不合法
    }
    LNode* q = p->next;
    p->next = q->next;
    free(q);
    return OK;
}

若i=0,头结点的next赋值给新指针next,释放头结点,把next再赋值给新的头结点

if(i==0){
ListNode* next=list->head->next;
free(list->head);
list->head=next;

}

最后更新链表的大小,即长度-1操作

3.链表应用

3.1数列计算

给n个数求和

#include<stdio.h>
#include<stdlio.h>
int main(){
	int n=0;
	while(scanf("%d",&n)!=EOF){
		if(n==0){
			break;
		}
		LinkList l;  //定义链表对象
		LinkListCreat (&l);
		for(int i=0;i<n;++i){
			int x;
			scanf("%d",&x);
			ListInsert(&l,i,x);//输入的数插入链表尾部
		}
		int sum=0;
		for(int i=0;i<n;++i){
			sum+=LinkListGet(&l,i)->data;
		}
		printf("%d\n",sum);
		LinkListDestroy(&l);//不销毁会导致内存泄漏
	}
	return 0;
} 

3.2超级楼梯

有一楼梯一个m层,没词只能跨1/2级,要走上m级,一共有几种走法。

input:先n,表示测试案例个数,再n行数据,每行包含一个整数m

用斐波那契数列表示即可。

4.代码实现

#include <stdio.h>
#include <malloc.h>

/**
 * Linked list of characters. The key is data.
 */
typedef struct LinkNode{
	char data;
	struct LinkNode *next;
} LNode, *LinkList, *NodePtr;

/**
 * Initialize the list with a header.
 * @return The pointer to the header.
 */
LinkList initLinkList(){
	NodePtr tempHeader = (NodePtr)malloc(sizeof(LNode));
	tempHeader->data = '\0';
	tempHeader->next = NULL;
	return tempHeader;
}// 初始化链表

/**
 * Print the list.
 * @param paraHeader The header of the list.
 */
void printList(NodePtr paraHeader){
	NodePtr p = paraHeader->next;
	while (p != NULL) {
		printf("%c", p->data);
		p = p->next;
	}// Of while
	printf("\r\n");
}// 打印链表

/**
 * Add an element to the tail.
 * @param paraHeader The header of the list.
 * @param paraChar The given char.
 */
void appendElement(NodePtr paraHeader, char paraChar){
	NodePtr p, q;

	// Step 1. Construct a new node.
	q = (NodePtr)malloc(sizeof(LNode));//定义一个新的结点
	q->data = paraChar;
	q->next = NULL;

	// Step 2. Search to the tail.
	p = paraHeader;
	while (p->next != NULL) {
		p = p->next;
	}// Of while

	// Step 3. Now add/link.
	p->next = q;
}// 在链表的结尾添加新的节点

/**
 * Insert an element to the given position.
 * @param paraHeader The header of the list.
 * @param paraChar The given char.
 * @param paraPosition The given position.
 */
void insertElement(NodePtr paraHeader, char paraChar, int paraPosition){
	NodePtr p, q;

	// Step 1. Search to the position.
	p = paraHeader;
	for (int i = 0; i < paraPosition; i ++) {
		p = p->next;
		if (p == NULL) {
			printf("The position %d is beyond the scope of the list.", paraPosition);
			return;
		}// Of if
	} // Of for i

	// Step 2. Construct a new node.
	q = (NodePtr)malloc(sizeof(LNode));
	q->data = paraChar;

	// Step 3. Now link.
	printf("linking\r\n");
	q->next = p->next;//将原来的节点的next的值赋给现在节点的next
	p->next = q;//连接新的节点
}// Of insertElement

/**
 * Delete an element from the list.
 * @param paraHeader The header of the list.
 * @param paraChar The given char.
 */
void deleteElement(NodePtr paraHeader, char paraChar){
	NodePtr p, q;
	p = paraHeader;
	while ((p->next != NULL) && (p->next->data != paraChar)){
		p = p->next;
	}// Of while

	if (p->next == NULL) {
		printf("Cannot delete %c\r\n", paraChar);
		return;
	}// Of if

	q = p->next;
	p->next = p->next->next;
	free(q);
}// Of deleteElement

/**
 * Unit test.
 */
void appendInsertDeleteTest(){
	// Step 1. Initialize an empty list.
	LinkList tempList = initLinkList();
	printList(tempList);

	// Step 2. Add some characters.
	appendElement(tempList, 'H');
	appendElement(tempList, 'e');
	appendElement(tempList, 'l');
	appendElement(tempList, 'l');
	appendElement(tempList, 'o');
	appendElement(tempList, '!');
	printList(tempList);

	// Step 3. Delete some characters (the first occurrence).
	deleteElement(tempList, 'e');
	deleteElement(tempList, 'a');
	deleteElement(tempList, 'o');
	printList(tempList);

	// Step 4. Insert to a given position.
	insertElement(tempList, 'o', 1);
	printList(tempList);
}// Of appendInsertDeleteTest

/**
 * Address test: beyond the book.
 */
void basicAddressTest(){
	LNode tempNode1, tempNode2;

	tempNode1.data = 4;
	tempNode1.next = NULL;

	tempNode2.data = 6;
	tempNode2.next = NULL;

	printf("The first node: %d, %d, %d\r\n",
		&tempNode1, &tempNode1.data, &tempNode1.next);
	printf("The second node: %d, %d, %d\r\n",
		&tempNode2, &tempNode2.data, &tempNode2.next);

	tempNode1.next = &tempNode2;
}// Of basicAddressTest

/**
 * The entrance.
 */
int main(){
	appendInsertDeleteTest();
}// Of main

运行结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值