链表的C语言实现

合集下载

c语言超时重发机制的链表

c语言超时重发机制的链表

c语言超时重发机制的链表C语言超时重发机制的链表在网络通信中,超时重发机制是一种常用的技术手段,用于确保数据的可靠传输。

而链表则是一种常见的数据结构,用于存储和管理数据。

本文将结合这两个概念,介绍如何使用链表实现C语言中的超时重发机制。

一、超时重发机制的概念超时重发机制是指在网络通信中,发送方发送数据后,如果在一定时间内未收到接收方的确认信息,发送方会将数据进行重发,以确保数据的可靠传输。

这一机制在保证数据可靠性的同时,也会带来一定的延迟和网络负载。

二、链表的概念及实现链表是一种动态数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。

链表的优点是可以动态地插入和删除节点,但缺点是访问节点时需要遍历整个链表。

在C语言中,链表可以使用结构体和指针来实现。

首先定义一个节点结构体,包含数据和指向下一个节点的指针:```typedef struct Node {int data; // 数据struct Node* next; // 指向下一个节点的指针} Node;```接下来,我们可以定义一个链表的结构体,包含指向链表头节点和尾节点的指针:```typedef struct LinkedList {Node* head; // 指向链表头节点的指针Node* tail; // 指向链表尾节点的指针} LinkedList;```初始化链表时,头节点和尾节点都为空:```void initLinkedList(LinkedList* list) {list->head = NULL;list->tail = NULL;}```插入节点时,需要创建一个新节点,并更新链表的头节点和尾节点指针:```void insertNode(LinkedList* list, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = NULL;if (list->head == NULL) {list->head = newNode;list->tail = newNode;} else {list->tail->next = newNode;list->tail = newNode;}}```三、使用链表实现超时重发机制在超时重发机制中,我们可以使用链表来保存待重发的数据包。

链表删除节点的方法c语言

链表删除节点的方法c语言

链表删除节点的方法c语言摘要:1.引言2.链表删除节点的原理3.单链表删除节点的实现4.双向链表删除节点的实现5.总结与拓展正文:【1】引言在计算机科学中,链表是一种常见的数据结构。

在实际应用中,链表的删除操作是非常重要的。

本文将介绍如何在C语言中实现链表的删除操作,主要包括单链表和双向链表的删除方法。

【2】链表删除节点的原理链表删除节点的主要原理是通过迭代或直接修改指针来实现。

在删除节点时,需要考虑以下几点:1.确定要删除的节点;2.更新前后相邻节点的指针;3.释放被删除节点的内存。

【3】单链表删除节点的实现单链表删除节点的核心代码如下:```cvoid deleteNode(Node* head, int target) {Node* p = head;Node* prev = NULL;while (p != NULL) {if (p->data == target) {if (prev == NULL) {head = p->next;} else {prev->next = p->next;}free(p);break;}prev = p;p = p->next;}}```这段代码首先定义了一个指向链表头的指针head,以及一个指向要删除节点的指针prev。

在while循环中,遍历链表的每个节点,当找到要删除的节点时,修改其相邻节点的指针,并释放被删除节点的内存。

【4】双向链表删除节点的实现双向链表删除节点的核心代码如下:```cvoid deleteNode(Node* head, int target) { Node* p = head;while (p != NULL) {if (p->data == target) {if (p->prev == NULL) {head = p->next;} else {p->prev->next = p->next;}if (p->next == NULL) {p->prev = NULL;} else {p->next->prev = p->prev;}free(p);break;}p = p->next;}}```这段代码与单链表删除节点的实现类似,主要区别在于双向链表需要维护prev指针,因此在删除节点时需要特别处理。

c语言实现通讯录管理系统(用链表实现)

c语言实现通讯录管理系统(用链表实现)

c语⾔实现通讯录管理系统(⽤链表实现)题⽬:通讯录(通过链表实现)设计并实现⼀个简易的通讯录软件,管理个⼈通讯记录。

⼀条通讯记录可包括:姓名、⼯作单位、⼿机、住宅电话、E-Mail、家庭住址等(可⾃⾏增删,但不可过少)。

该系统应实现以下基本功能:(1)增加新的通讯记录。

(2)删除已有的通讯记录。

(3)修改已有的通讯记录。

(4)浏览全部或指定(如指定姓名、⼯作单位等)的通讯记录。

(5)合理组织排列各项功能,界⾯可使⽤键盘操作。

(6)以⽂件的形式存储数据。

说明:⼤⼀时的c语⾔课设,⽤链表实现⼀个通讯录管理系统,为了美观好看,花了很多时间调整齐度,记录⼀下⼤⼀时的作业。

其主要功能是对通讯录可输⼊,显⽰,插⼊,删除,最难是可保存,这个学⽂件的时候不怎么会。

内容我⾃⼰弄了7个,名字,性别,⼯作单位,⼿机,住宅电话,E-Mail,家庭住址(其他太多其实都是⼀样的,就懒得加了)。

主要运⽤到对指针中的链表的功能和使⽤要⽐较扎实,分部列写就可以了。

实现图⽚:附上代码:1 #include <stdio.h>2 #include <string.h>3 #include <stdlib.h>4 typedef struct student5 {6char name[20];//名字7char wm[20];//性别8char work[100];//⼯作单位9char stel[20];//⼿机10char htel[20];//住宅号码11char mail[20];//E-Mail12char home[100];//家庭住址13struct student *next;14 }stu;15 stu *head;//头指针16void screen()//主菜单17 {18 printf("\n=======================================================\n");19 printf(" 欢迎来到通讯录管理系统\n\n");20 printf(" 1.输⼊数据 2.显⽰数据\n");21 printf(" 3.插⼊数据 4.删除数据\n");22 printf(" 5.查看数据 6.修改数据\n");23 printf(" 7.保存数据 8.返回主菜单\n");24 printf("\n~~~~~~输~~~~~~⼊~~~~~~9~~~~~~退~~~~~~出~~~~~~程~~~~~~序\n");25 }26void input()//输⼊数据27 {28int ans;//判断是否继续输⼊29 stu *p1,*p2;30 p1=(stu *)malloc(sizeof(stu));//申请内存来⽤31if(p1!=NULL)32 {33 printf("========输⼊数据========\n");34 head=p1;35while(1)36 {37 printf("名字:");38 scanf("%s",&p1->name);39 printf("性别:");40 scanf("%s",&p1->wm);41 printf("⼯作单位:");42 scanf("%s",&p1->work);43 printf("⼿机:");44 scanf("%s",&p1->stel);45 printf("住宅号码:");46 scanf("%s",&p1->htel);47 printf("E-Mail:");48 scanf("%s",&p1->mail);49 printf("家庭地址:");50 scanf("%s",&p1->home);51 printf("===================================\n");52 p2=p1;53 p1=(stu *)malloc(sizeof(stu));//申请下⼀个要⽤的空间54if(p1!=NULL)55 p2->next=p1;56 printf("请选择是否继续输⼊:1.继续 2.退出\n请选择:");//⽤户选择57 scanf("%d",&ans);58if(ans==1)//继续59continue;60else//退出61 {62 printf("========输⼊完毕========\n");63 p2->next=NULL;64free(p1);//将申请的的⽆⽤内存释放65break;66 }67 }68 }69 }70void look(stu *p1)//显⽰数据71 {72 printf("========显⽰数据========\n");73while(p1!=NULL)74 {75 printf("名字:%s\n",p1->name);76 printf("性别:%s\t",p1->wm);77 printf("⼯作单位:%s\t",p1->work);78 printf("⼿机:%s\t",p1->stel);79 printf("住宅号码:%s\t",p1->htel);80 printf("E-Mail:%s\t",p1->mail);81 printf("家庭住址:%s\n",p1->home);82 printf("=====================================\n");83 p1=p1->next;84 }85 printf("========显⽰完毕========\n");86 }87void insert()//插⼊数据88 {89int ans;//选择插⼊位置90char name[20];//插⼊者的名字91 printf("========插⼊数据========\n");92 stu *p1,*p2,*p3;93 p1=head;94 p3=(stu *)malloc(sizeof(stu));//申请内存95 p3->next=NULL;96 printf("请输⼊插⼊者的数据:\n");97 printf("名字:");98 scanf("%s",&p3->name);99 printf("性别:");100 scanf("%s",&p3->wm);101 printf("⼯作单位:");102 scanf("%s",&p3->work);103 printf("⼿机:");104 scanf("%s",&p3->stel);105 printf("住宅号码:");106 scanf("%s",&p3->htel);107 printf("E-Mail:");108 scanf("%s",&p3->mail);109 printf("家庭地址:");110 scanf("%s",&p3->home);111 printf("请选择插⼊位置:1.⾸位置插⼊ 2.尾部插⼊ 3.插到某⼈前⾯\n请选择:");112 scanf("%d",&ans);113switch(ans)114 {115case1://放到头指针116 p3->next=p1;117 head=p3;118break;119case2://放到尾部120while(p1->next!=NULL)121 p1=p1->next;122 p1->next=p3;123break;124case3://放到某⼈前⾯125 printf("请输⼊插到谁前⾯名字:");126 scanf("%s",name);127while(strcmp(name,p1->name)!=0)128 {129 p2=p1;130 p1=p1->next;131 }132 p2->next=p3;133 p3->next=p1;134break;135 }136 printf("========插⼊成功========\n");137 }138void deleted()//删除数据139 {140 stu *p1,*p2;141char name[20];//删除者名字142 printf("========删除数据========\n");143 printf("请输⼊要删除者的名字:");144 scanf("%s",name);145 p1=head;146if(head==NULL)//通讯录已经没数据了147 {148 printf("通讯录⾥什么也没有了。

《数据结构(C语言版)》严蔚敏代码实现———链表

《数据结构(C语言版)》严蔚敏代码实现———链表

《数据结构(C语⾔版)》严蔚敏代码实现———链表⼀、前⾔哈喽,⼤家好~我是熊⼦q,我⼜来了!他来了他来了,他带着代码过来了!今天要分享的代码是链表!快快搬着⼩板凳!⼆、代码严奶奶的书中预定义了⼀些预定义常量和类型,⼤家可以 新建⼀个y.h⽂件粘贴以下内容, 然后再去复制代码哦。

y.h⽂件内容:/*** 严奶奶书中的预定义常量和类型**///函数结果状态代码#define TRUE 1 //成功#define FALSE 0 //失败#define OK 1 //成功#define ERROR 0 //错误#define INFEASIBLE -1 //不可实⾏#define OVERFLOW -2 //溢出//Status 是函数的类型,其值是函数结果状态代码typedef int Status;链表LinkList.cpp:#include "y.h"#include <iostream>#include <cstdlib>#include <cstdio>using namespace std;typedef int ElemType;/*** 严奶奶单链表的实现* by 熊⼦q 2021.2.1**/typedef struct LNode{ElemType data;struct LNode *next;}LNode,*LinkList;//获取元素Status GetElem(LinkList L, int i, ElemType &e){//L为带头结点的单链表的头指针//当第i个元素存在时,其值赋给e并返回OK,否则返回ERRORLNode *p = L->next; //p指向第⼀个结点int j = 1; //j为计数器while(p && j<i){ //寻找第i个位置p = p->next;++j;}if(!p || j>i) return ERROR; //第i个元素不存在e = p->data; //否则获取第i个元素return OK;}//插⼊元素,时间复杂度O(n)Status Insert(LinkList &L, int i, ElemType e){//在带头结点的单链表L中第i个位置之前插⼊元素eLNode *p = L;int j = 0;while(p && j<i-1){p = p->next;++j;}if(!p || j>i-1) return ERROR; //i⼩于1或者⼤于表长加1LNode *q = (LNode*)malloc(sizeof(LNode));q->data = e; //插⼊数据q->next = p->next;p->next = q;return OK;}//删除元素,时间复杂度O(n)Status ListDelete(LinkList &L, int i, ElemType e){//在带头结点的单链表L中,删除第i个元素,并由e返回其值LNode *p = L->next;int j = 1;while(p && j<i-1){p = p->next;++j;} //寻找i的前驱元素if(!(p->next) || j>i-1) return ERROR; //删除位置不合理,i元素不存在或 LNode *q = p->next; //删除第i个位置元素,并释放该结点 p->next = q->next;e = q->data;free(q);return OK;}//创建链表void CreateList(LinkList &L, int n){//逆序输⼊n个元素的值,建⽴带头结点的单链表LL = (LinkList)malloc(sizeof(LNode));L->next = NULL; //建⽴⼀个头结点printf("请输⼊数据:\n");for(int i=n;i>0;--i){LNode *p = (LNode*)malloc(sizeof(LNode));scanf("%d",&(p->data));p->next = L->next; L->next = p;}}//合并两个有序链表void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc){//已知单链表La和Lb的元素按值⾮递减排列//归并La和Lb得到新的单链表Lc,Lc的元素也按值⾮递减排列LNode *pa = La->next;LNode *pb = Lb->next;LNode *pc = La; //⽤La的头结点作为Lc的头结点Lc = pc;while(pa && pb){//取⼆者中较⼤值添加到Lc中if(pa->data > pb->data){//先添加该节点为pc的后继元素,然后pc和pa指针都后移pc->next = pa; pc = pc->next; pa = pa->next;}else{pc->next = pb; pc = pc->next; pb = pb->next;}}pc->next = pa? pa: pb; //插⼊剩余段free(Lb); //释放Lb的头结点}//输出单链表void Display(LinkList &L){LNode *p = L->next;printf("单链表的内容为:");while(p){printf("%d",p->data);if(p->next) printf("->");else printf("\n");p = p->next;}}int main(){LinkList l;CreateList(l, 5);Display(l);// printf("在第%d位插⼊%d",1,123);// Insert(l, 1, 123);// Display(l);int tmp;GetElem(l, 2, tmp);printf("%d",tmp);return 0;}三、运⾏截图四、附录如果你想看其他的代码,下⾯有链接哦:。

C语言链表数据结构实现

C语言链表数据结构实现

C语言链表数据结构实现链表是一种常见的数据结构,用于存储和操作数据集合。

它由节点(Node)组成,每个节点包含数据部分和指向下一个节点的指针。

在C语言中,我们可以使用指针来实现链表数据结构。

1. 定义节点结构体首先,我们需要定义链表的节点结构体。

节点结构体由数据部分和指向下一个节点的指针组成。

下面是一个示例:```typedef struct Node {int data;struct Node* next;} Node;```2. 创建链表接下来,我们可以编写创建链表的函数。

该函数将返回链表的头节点,并初始化为空。

示例代码如下:```Node* createLinkedList() {return NULL;}```3. 插入节点链表的插入操作包括在链表的任意位置插入新节点。

我们可以编写一个插入节点的函数,根据需求选择在链表的头部、尾部或指定位置插入节点。

示例代码如下:```void insertNode(Node** head, int data, int position) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;if (position == 0) {newNode->next = *head;*head = newNode;} else {Node* current = *head;int currentPosition = 0;while (currentPosition < position - 1 && current != NULL) {current = current->next;currentPosition++;}if (current != NULL) {newNode->next = current->next;current->next = newNode;}}}```4. 删除节点链表的删除操作可以删除链表的任意节点。

C语言单向循环链表实现实现约瑟夫环

C语言单向循环链表实现实现约瑟夫环

C语言实现约瑟夫环问题------单向循环链表实现问题描述:有n个人围成一圈进行报数游戏,从第一个人开始报到m的人出圈,接下来有从下一个人开始,。

一次这样往复,直到最后一个人也出圈,求他们的出圈顺序?(例如8个人,凡报3的人出圈,则他们出圈顺序是3 ,6, 1,,5 ,2 ,8,4 ,7)#include<stdio.h>#include<stdlib.h>typedef struct node{int value;struct node *next;}NODE;//*********************建立循环链表(尾插法建立)***********//NODE *createlink(int number){NODE *head=NULL,*p=NULL,*q=NULL;int i=1;head=(struct node*)malloc(sizeof(struct node)); //***建立第一个节点***//head->value=i;p=head;for(i=2;i<=number;i++) //***建立剩下的number-1节点****//{q=(struct node*)malloc(sizeof(struct node));if(q==0) return 0;p->next=q;p=q;p->value=i;}p->next=head;return head;}//*****************建立约瑟夫环********************// void jose(NODE *p,int number,int n){int i,j,g=0;NODE *q=NULL;for(i=1;i<=number;i++){for(j=1;j<n-1;j++){p=p->next;}q=p->next; //***q用来记录要删除的节点*****//p->next=q->next; //****删去q节点******//p=p->next;printf("第%3d个出圈号是:%3d\n",i,q->value);free(q);}printf("\n");// p->next=NULL; 此表达式不能出现在此处,最后一个节点删除后就不存在了}//***********************主函数*************************//int main( ){int number=0;int n=0;printf("请输入总人数number和出拳编号n:\n");scanf("%d",&number);scanf("%d",&n);NODE *head=NULL;head=createlink(number);jose(head,number,n);system("PAUSE");return 1;}。

[转载整理]C语言链表实例

[转载整理]C语言链表实例

[转载整理]C语⾔链表实例 C语⾔链表有单链表、双向链表、循环链表。

单链表由数据域和指针域组成,数据域存放数据,指针域存放该数据类型的指针便于找到下⼀个节点。

双链表则含有头指针域、数据域和尾指针域,域单链表不同,双链表可以从后⼀个节点找到前⼀个节点,⼆单链表则不⾏。

循环链表就是在单链表的基础上,将头结点的地址指针存放在最后⼀个节点的指针域⾥以,此形成循环。

此外还有双向循环链表,它同时具有双向链表和循环链表的功能。

单链表如:链表节点的数据结构定义struct node{int num;struct node *p;} ;在此链表节点的定义中,除⼀个整型的成员外,成员p是指向与节点类型完全相同的指针。

※在链表节点的数据结构中,⾮常特殊的⼀点就是结构体内的指针域的数据类型使⽤了未定义成功的数据类型。

这是在C中唯⼀规定可以先使⽤后定义的数据结构。

链表实例代码:1// 原⽂地址 /wireless-dragon/p/5170565.html2 #include<stdio.h>3 #include<stdlib.h>4 #include<string.h>56 typedef int elemType;//定义存⼊的数据的类型可以是int char78 typedef struct NODE{ //定义链表的结构类型9 elemType element;10struct NODE *next;11 }Node;1213/************************************************************************/14/* 以下是关于线性表链接存储(单链表)操作的19种算法 */1516/* 1.初始化线性表,即置单链表的表头指针为空 */17/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/18/* 3.打印链表,链表的遍历*/19/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */20/* 5.返回单链表的长度 */21/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */22/* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停⽌程序运⾏ */23/* 8.从单链表中查找具有给定值x的第⼀个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */24/* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */25/* 10.向单链表的表头插⼊⼀个元素 */26/* 11.向单链表的末尾添加⼀个元素 */27/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0 */28/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */29/* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏ */30/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */31/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */32/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */33/* 18.交换2个元素的位置 */34/* 19.将线性表进⾏冒排序 */35363738/*注意检查分配到的动态内存是否为空*/3940414243/* 1.初始化线性表,即置单链表的表头指针为空 */44void initList(Node **pNode)45 {46 *pNode=NULL;47 printf("initList函数执⾏,初始化成功\n");48 }4950/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/51 Node *creatList(Node *pHead)52 {53 Node *p1,*p2;54 p1=p2=(Node *)malloc(sizeof(Node));55if(p1 == NULL || p2 ==NULL)57 printf("内存分配失败\n");58 exit(0);59 }60 memset(p1,0,sizeof(Node));6162 scanf("%d",&p1->element);63 p1->next=NULL;6465while(p1->element >0) //输⼊的值⼤于0则继续,否则停⽌66 {67if(pHead == NULL)//空表,接⼊表头68 {69 pHead=p1;70 }71else72 {73 p2->next=p1;74 }7576 p2=p1;77 p1=(Node *)malloc(sizeof(Node));7879if(p1==NULL||p2==NULL)80 {81 printf("内存分配失败\n");82 exit(0);83 }84 memset(p1,0,sizeof(Node));85 scanf("%d",&p1->element);86 p1->next=NULL;87 }88 printf("CreatList函数执⾏,链表创建成功\n");89return pHead;90 }9192/* 3.打印链表,链表的遍历*/93void printList(Node *pHead)94 {95if(NULL==pHead)96 {97 printf("PrintList函数执⾏,链表为空\n");98 }99else100 {101while(NULL!=pHead)102 {103 printf("%d\n",pHead->element);104 pHead=pHead->next;105 }106 }107108 }109110111/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */ 112void clearList(Node *pHead)113 {114 Node *pNext;115116if(pHead==NULL)117 {118 printf("clearList函数执⾏,链表为空\n");119return;120 }121while(pHead->next!=NULL)122 {123 pNext=pHead->next;124free(pHead);125 pHead=pNext;126 }127 printf("clearList函数执⾏,链表已经清除!\n");128129 }130131/* 5.返回链表的长度*/132int sizeList(Node *pHead)133 {134int size=0;135136while(pHead!=NULL)137 {138 size++;139 pHead=pHead->next;141 printf("sizelist函数执⾏,链表长度为%d\n",size);142return size;143 }144145/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */146int isEmptyList(Node *pHead)147 {148if(pHead==NULL)149 {150 printf("isEmptylist函数执⾏,链表为空!\n");151return1;152 }153154else155 printf("isEmptylist函数执⾏,链表⾮空!\n");156return0;157158 }159160/* 7.返回链表中第post节点的数据,若post超出范围,则停⽌程序运⾏*/161int getElement(Node *pHead,int pos)162 {163int i=0;164if(pos<1)165 {166 printf("getElement函数执⾏,pos值⾮法!");167return0;168 }169if(pHead==NULL)170 {171 printf("getElement函数执⾏,链表为空!");172 }173174while (pHead!=NULL)175 {176 ++i;177if(i==pos)178 {179break;180 }181 pHead=pHead->next;182 }183if(i<pos)184 {185 printf("getElement函数执⾏,pos值超出链表长度\n");186return0;187 }188 printf("getElement函数执⾏,位置%d中的元素为%d\n",pos,pHead->element);189190return1;191 }192193//8.从单⼀链表中查找具有给定值x的第⼀个元素,若查找成功后,返回该节点data域的存储位置,否则返回NULL 194 elemType *getElemAddr(Node *pHead,elemType x)195 {196if(NULL==pHead)197 {198 printf("getEleAddr函数执⾏,链表为空");199return NULL;200 }201if(x<0)202 {203 printf("getEleAddr函数执⾏,给定值x不合法\n");204return NULL;205 }206while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素207 {208 pHead=pHead->next;209 }210if(pHead->element!=x)211 {212 printf("getElemAddr函数执⾏,在链表中没有找到x值\n");213return NULL;214 }215else216 {217 printf("getElemAddr函数执⾏,元素%d的地址为0x%x\n",x,&(pHead->element));218 }219return &(pHead->element);220221 }222223224/*9.修改链表中第pos个点X的值,如果修改成功,则返回1,否则返回0*/225int modifyElem(Node *pNode,int pos,elemType x)226 {227 Node *pHead;228 pHead=pNode;229int i=0;230if(NULL==pHead)231 {232 printf("modifyElem函数执⾏,链表为空\n");233return0;234 }235236if(pos<1)237 {238 printf("modifyElem函数执⾏,pos值⾮法\n");239return0;240 }241242while(pHead!= NULL)243 {244 ++i;245if(i==pos)246 {247break;248 }249 pHead=pHead->next;250 }251252if(i<pos)253 {254 printf("modifyElem函数执⾏,pos值超出链表长度\n");255return0;256 }257 pNode=pHead;258 pNode->element=x;259 printf("modifyElem函数执⾏,修改第%d点的元素为%d\n",pos,x);260261return1;262263 }264265/* 10.向单链表的表头插⼊⼀个元素 */266int insertHeadList(Node **pNode,elemType insertElem)267 {268 Node *pInsert;269 pInsert=(Node *)malloc(sizeof(Node));270if(pInsert==NULL) exit(1);271 memset(pInsert,0,sizeof(Node));272 pInsert->element=insertElem;273 pInsert->next=*pNode;274 *pNode=pInsert;275 printf("insertHeadList函数执⾏,向表头插⼊元素%d成功\n",insertElem);276return1;277 }278279/* 11.向单链表的末尾添加⼀个元素 */280int insertLastList(Node *pNode,elemType insertElem)281 {282 Node *pInsert;283 Node *pHead;284 Node *pTmp;285286 pHead=pNode;287 pTmp=pHead;288 pInsert=(Node *)malloc(sizeof(Node));289if(pInsert==NULL) exit(1);290 memset(pInsert,0,sizeof(Node));291 pInsert->element=insertElem;292 pInsert->next=NULL;293while(pHead->next!=NULL)294 {295 pHead=pHead->next;296 }297 pHead->next=pInsert;298 printf("insertLastList函数执⾏,向表尾插⼊元素%d成功!\n",insertElem);299return1;300 }301302/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0*/ 303int isAddPos(Node *pNode,int pos,elemType x)304 {305 Node *pHead;306 pHead=pNode;307 Node *pTmp;308int i=0;309310if(NULL==pHead)311 {312 printf("AddPos函数执⾏,链表为空\n");313return0;314 }315316if(pos<1)317 {318 printf("AddPos函数执⾏,pos值⾮法\n");319return0;320 }321322while(pHead!=NULL)323 {324 ++i;325if(i==pos)326break;327 pHead=pHead->next;328 }329330if(i<pos)331 {332 printf("AddPos函数执⾏,pos值超出链表长度\n");333return0;334 }335336 pTmp=(Node *)malloc(sizeof(Node));337if(pTmp==NULL) exit(1);338 memset(pTmp,0,sizeof(Node));339 pTmp->next=pHead->next;340 pHead->next=pTmp;341 pTmp->element=x;342343 printf("AddPos函数执⾏成功,向节点%d后插⼊数值%d\n",pos,x); 344return1;345 }346347/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */348int OrrderList(Node *pNode,elemType x)349 {350//注意如果此数值要排到⾏尾要修改本代码351 Node *pHead;352 pHead=pNode;353 Node *pTmp;354355if(NULL==pHead)356 {357 printf("OrrderList函数执⾏,链表为空\n");358return0;359 }360361if(x<1)362 {363 printf("OrrderList函数执⾏,x值⾮法\n");364return0;365 }366367while(pHead!=NULL)368 {369if((pHead->element)>=x)370break;371 pHead=pHead->next;372 }373374375if(pHead==NULL)376 {377 printf("OrrderList函数查找完毕,该函数中没有该值\n");378return0;379 }380381382 pTmp=(Node *)malloc(sizeof(Node));383if(pTmp==NULL) exit(1);384 memset(pTmp,0,sizeof(Node));385 pTmp->next=pHead->next;386 pHead->next=pTmp;387 pTmp->element=x;388389 printf("OrrderList函数成功插⼊数值%d\n",x);390return1;391 }392393/*14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏*/ 394int DelHeadList(Node **pList)395 {396 Node *pHead;397 pHead=*pList;398if(pHead!=NULL)399 printf("DelHeadList函数执⾏,函数⾸元素为%d删除成功\n",pHead->element); 400else401 {402 printf("DelHeadList函数执⾏,链表为空!");403return0;404 }405 *pList=pHead->next;406return1;407 }408409/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */410int DelLastList(Node *pNode)411 {412 Node *pHead;413 Node *pTmp;414415 pHead=pNode;416while(pHead->next!=NULL)417 {418 pTmp=pHead;419 pHead=pHead->next;420 }421 printf("链表尾删除元素%d成功!\n",pHead->element);422free(pHead);423 pTmp->next=NULL;424return1;425 }426427/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */ 428int DelPos(Node *pNode,int pos)429 {430 Node *pHead;431 pHead=pNode;432 Node *pTmp;433434int i=0;435436if(NULL==pHead)437 {438 printf("DelPos函数执⾏,链表为空\n");439return0;440 }441442if(pos<1)443 {444 printf("DelPos函数执⾏,pos值⾮法\n");445return0;446 }447448while(pHead!=NULL)449 {450 ++i;451if(i==pos)452break;453 pTmp=pHead;454 pHead=pHead->next;455 }456457if(i<pos)458 {459 printf("DelPos函数执⾏,pos值超出链表长度\n");460return0;461 }462 printf("DelPos函数执⾏成功,节点%d删除数值%d\n",pos,pHead->element); 463 pTmp->next=pHead->next;464free(pHead);465return1;466 }467468/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */469int Delx(Node **pNode,int x)470 {471 Node *pHead;472 Node *pTmp;473 pHead=*pNode;474int i=0;475476if(NULL==pHead)477 {478 printf("Delx函数执⾏,链表为空");479return0;480 }481if(x<0)482 {483 printf("Delx函数执⾏,给定值x不合法\n");484return0;485 }486while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素487 {488 ++i;489 pTmp=pHead;490 pHead=pHead->next;491 }492if(pHead->element!=x)493 {494 printf("Delx函数执⾏,在链表中没有找到x值\n");495return0;496 }497if((i==0)&&(NULL!=pHead->next))498 {499 printf("Delx函数执⾏,在链表⾸部找到此元素,此元素已经被删除\n");500 *pNode=pHead->next;501free(pHead);502return1;503 }504 printf("Delx函数执⾏,⾸个为%d元素被删除\n",x);505 pTmp->next=pHead->next;506free(pHead);507return1;508 }509510/* 18.交换2个元素的位置 */511int exchange2pos(Node *pNode,int pos1,int pos2)512 {513 Node *pHead;514int *pTmp;515int *pInsert;516int a;517int i=0;518519if(pos1<1||pos2<1)520 {521 printf("DelPos函数执⾏,pos值⾮法\n");522return0;523 }524525 pHead=pNode;526while(pHead!=NULL)527 {528 ++i;529if(i==pos1)530break;531 pHead=pHead->next;532 }533534if(i<pos1)535 {536 printf("DelPos函数执⾏,pos1值超出链表长度\n");537return0;538 }539540 pTmp=&(pHead->element);541 i=0;542 pHead=pNode;543while(pHead!=NULL)544 {545 ++i;546if(i==pos2)547break;548 pHead=pHead->next;549 }550551if(i<pos2)552 {553 printf("DelPos函数执⾏,pos2值超出链表长度\n");554return0;555 }556557 pInsert=&(pHead->element);558 a=*pTmp;559 *pTmp=*pInsert;560 *pInsert=a;561562 printf("DelPos函数执⾏,交换第%d个和第%d个pos点的值\n",pos1,pos2); 563return1;564 }565566int swap(int *p1,int *p2)567 {568int a;569if(*p1>*p2)570 {571 a=*p1;572 *p1=*p2;573 *p2=a;574 }575return0;576 }577578/* 19.将线性表进⾏冒泡排序 */579int Arrange(Node *pNode)580 {581 Node *pHead;582 pHead=pNode;583584int a=0,i,j;585586if(NULL==pHead)587 {588 printf("Arrange函数执⾏,链表为空\n");589return0;590 }591592while(pHead!=NULL)593 {594 ++a;595 pHead=pHead->next;596 }597598 pHead=pNode;599for(i=0;i<a-1;i++)600 {601for(j=1;j<a-i;j++)602 {603 swap(&(pHead->element),&(pHead->next->element));604 pHead=pHead->next;605 }606 pHead=pNode;607 }608 printf("Arrange函数执⾏,链表排序完毕!\n");609return0;610 }611612int main()613 {614 Node *pList=NULL;615int length=0;616617 elemType posElem;618619 initList(&pList);620 printList(pList);621622 pList=creatList(pList);623 printList(pList);624625 sizeList(pList);626 printList(pList);627628 isEmptyList(pList);629630631 posElem=getElement(pList,3);632 printList(pList);633634 getElemAddr(pList,5);635636 modifyElem(pList,4,1);637 printList(pList);638639 insertHeadList(&pList,5);640 printList(pList);641642 insertLastList(pList,10);643 printList(pList);644645 isAddPos(pList,4,5); 646 printList(pList);647648 OrrderList(pList,6);649 printList(pList);650651 DelHeadList(&pList); 652 printList(pList);653654 DelLastList(pList);655 printList(pList);656657 DelPos(pList,5);658 printList(pList);659660 Delx(&pList,5);661 printList(pList);662663 exchange2pos(pList,2,5); 664 printList(pList);665666 Arrange(pList);667 printList(pList);668669 clearList(pList);670return0;671 }。

哈希链表的c语言实现

哈希链表的c语言实现

哈希链表的c语言实现哈希链表的C语言实现哈希链表是一种常用的数据结构,用于存储和操作大量的数据。

它结合了哈希表和链表的特点,具有快速查找和高效插入删除的优势。

本文将介绍如何使用C语言实现哈希链表,并详细讲解其原理和操作。

一、哈希链表的原理哈希链表是通过哈希函数将数据的键映射到一个唯一的索引位置,然后使用链表来解决哈希冲突。

哈希函数可以是简单的取模运算,也可以是复杂的算法,关键在于保证映射的唯一性和均匀性。

二、哈希链表的结构在C语言中,我们可以使用结构体来定义哈希链表的节点和链表本身。

节点包含一个键值对,即存储的数据和对应的键,以及一个指向下一个节点的指针。

链表则包含一个指向第一个节点的指针。

```c// 定义哈希链表节点typedef struct Node {int key;int value;struct Node* next;} Node;// 定义哈希链表typedef struct HashTable {int size;Node** table;} HashT able;```三、哈希链表的操作1. 初始化哈希链表在初始化哈希链表时,需要指定链表的大小,并分配相应大小的内存空间。

同时,需要将每个节点的指针初始化为空。

2. 插入节点插入节点时,首先通过哈希函数计算出节点的索引位置,然后将节点插入到对应索引位置的链表中。

如果该位置已经存在节点,则将新节点插入到链表的头部。

3. 查找节点查找节点时,也需要通过哈希函数计算出节点的索引位置,然后遍历链表,找到对应的节点。

如果找到了节点,则返回节点的值;否则,返回空。

删除节点时,首先通过哈希函数计算出节点的索引位置,然后遍历链表,找到对应的节点并删除。

需要注意的是,删除节点时需要维护链表的连续性。

四、示例代码下面是一个简单的示例代码,演示了如何使用C语言实现哈希链表的初始化、插入、查找和删除操作。

```c#include <stdio.h>#include <stdlib.h>// 初始化哈希链表HashTable* initHashTable(int size) {HashTable* ht = (HashTable*)malloc(sizeof(HashTable));ht->size = size;ht->table = (Node**)malloc(sizeof(Node*) * size);for (int i = 0; i < size; i++) {ht->table[i] = NULL;}return ht;}void insertNode(HashTable* ht, int key, int value) { int index = key % ht->size;Node* newNode = (Node*)malloc(sizeof(Node)); newNode->key = key;newNode->value = value;newNode->next = ht->table[index];ht->table[index] = newNode;}// 查找节点int findNode(HashTable* ht, int key) {int index = key % ht->size;Node* cur = ht->table[index];while (cur) {if (cur->key == key) {return cur->value;}cur = cur->next;}return -1;}void deleteNode(HashTable* ht, int key) { int index = key % ht->size;Node* cur = ht->table[index];Node* pre = NULL;while (cur) {if (cur->key == key) {if (pre) {pre->next = cur->next;} else {ht->table[index] = cur->next; }free(cur);return;}pre = cur;cur = cur->next;}}int main() {HashTable* ht = initHashTable(10);insertNode(ht, 1, 10);insertNode(ht, 2, 20);insertNode(ht, 11, 30);printf("%d\n", findNode(ht, 1));printf("%d\n", findNode(ht, 2));printf("%d\n", findNode(ht, 11));deleteNode(ht, 2);printf("%d\n", findNode(ht, 2));free(ht->table);free(ht);return 0;}```五、总结本文介绍了哈希链表的C语言实现,并详细讲解了其原理和操作。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

链表的C语言实现分类:计算机学习2006.12.29 09:06 作者:ybxycy | 评论:0 | 阅读:652数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了灵活性。

但数组也同样存在一些弊病。

如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序设计中针对不同问题有时需要3 0个大小的数组,有时需要5 0个数组的大小,难于统一。

我们只能够根据可能的最大需求来定义数组,常常会造成一定存储空间的浪费。

我们希望构造动态的数组,随时可以调整数组的大小,以满足不同问题的需要。

链表就是我们需要的动态数组。

它是在程序的执行过程中根据需要有数据存储就向系统要求申请存储空间,决不构成对存储区的浪费。

链表是一种复杂的数据结构,其数据之间的相互关系使链表分成三种:单链表、循环链表、双向链表,下面将逐一介绍。

7.4.1 单链表图7 - 3是单链表的结构。

单链表有一个头节点h e a d,指向链表在内存的首地址。

链表中的每一个节点的数据类型为结构体类型,节点有两个成员:整型成员(实际需要保存的数据)和指向下一个结构体类型节点的指针即下一个节点的地址(事实上,此单链表是用于存放整型数据的动态数组)。

链表按此结构对各节点的访问需从链表的头找起,后续节点的地址由当前节点给出。

无论在表中访问那一个节点,都需要从链表的头开始,顺序向后查找。

链表的尾节点由于无后续节点,其指针域为空,写作为N U L L。

图7 - 3还给出这样一层含义,链表中的各节点在内存的存储地址不是连续的,其各节点的地址是在需要时向系统申请分配的,系统根据内存的当前情况,既可以连续分配地址,也可以跳跃式分配地址。

看一下链表节点的数据结构定义:struct node{int num;struct node *p;} ;在链表节点的定义中,除一个整型的成员外,成员p是指向与节点类型完全相同的指针。

在链表节点的数据结构中,非常特殊的一点就是结构体内的指针域的数据类型使用了未定义成功的数据类型。

这是在C中唯一规定可以先使用后定义的数据结构。

? 单链表的创建过程有以下几步:1 ) 定义链表的数据结构。

2 ) 创建一个空表。

3 ) 利用m a l l o c ( )函数向系统申请分配一个节点。

4 ) 将新节点的指针成员赋值为空。

若是空表,将新节点连接到表头;若是非空表,将新节点接到表尾。

5 ) 判断一下是否有后续节点要接入链表,若有转到3 ),否则结束。

? 单链表的输出过程有以下几步1) 找到表头。

2) 若是非空表,输出节点的值成员,是空表则退出。

3 ) 跟踪链表的增长,即找到下一个节点的地址。

4) 转到2 )。

[例7-5] 创建一个存放正整数(输入- 9 9 9做结束标志)的单链表,并打印输出。

#include <stdlib.h> /包*含ma l l o c ( ) 的头文件*/#include <stdio.h>struct node /*链表节点的结构* /{int num;struct node *next;} ;m a i n ( ){struct node *creat(); / *函数声明* /void print();/ *函数声明* /struct node *head; / * 定义头指针* /head=NULL;/*建一个空表*/head=creat(head);/*函数调用,创建单链表*/print(head);/*打印单链表*/}/******************************************/struct node*creat(struct node*head)函/数*返回的是与节点相同类型的指针*/ {struct node*p1,*p2;p1=p2=(struct node*)malloc(sizeof(struct node));申请/*新节点*/scanf("%d",&p1->num);/*输入节点的值*/p1->next=NULL;/*将新节点的指针置为空*/while(p1->num>0)/*输入节点的数值大于0*/{if(head==NULL)head=p1;/*空表,接入表头*/else p2->next=p1;/*非空表,接到表尾*/p2=p1;p1=(struct node*)malloc(sizeof(struct node));申/请*下一个新节点*/scanf("%d",&p1->num);/*输入节点的值*/}return head;/*返回链表的头指针*/}/*******************************************/void print(struct node*head)输/*出以head为头的链表各节点的值*/{struct node *temp;temp=head;/*取得链表的头指针*/while(temp!=NULL)/*只要是非空表*/{printf("%6d",temp->num);/*输出链表节点的值*/temp=temp->next;/*跟踪链表增长*/}}在链表的创建过程中,链表的头指针是非常重要的参数。

因为对链表的输出和查找都要从链表的头开始,所以链表创建成功后,要返回一个链表头节点的地址,即头指针。

一、单链表的建立有了动态内存分配的基础,要实现链表就不难了。

所谓链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。

链表又分为单链表、双向链表和循环链表等。

我们先讲讲单链表。

所谓单链表,是指数据接点是单向排列的。

一个单链表结点,其结构类型分为两部分:1、数据域:用来存储本身数据2、链域或称为指针域:用来存储下一个结点地址或者说指向其直接后继的指针。

例:typedef struct node{char name[20];struct node *link;}stud;这样就定义了一个单链表的结构,其中char name[20]是一个用来存储姓名的字符型数组,指针*link是一个用来存储其直接后继的指针。

定义好了链表的结构之后,只要在程序运行的时候爱数据域中存储适当的数据,如有后继结点,则把链域指向其直接后继,若没有,则置为NULL。

下面就来看一个建立带表头(若未说明,以下所指链表均带表头)的单链表的完整程序。

#include <stdio.h>#include <malloc.h> /*包含动态内存分配函数的头文件*/#define N 10 /*N为人数*/typedef struct node{char name[20];struct node *link;}stud;stud * creat(int n) /*建立单链表的函数,形参n为人数*/{stud *p,*h,*s; /* *h保存表头结点的指针,*p指向当前结点的前一个结点,*s指向当前结点*/int i; /*计数器*/if((h=(stud *)malloc(sizeof(stud)))==NULL) /*分配空间并检测*/{printf("不能分配内存空间!");exit(0);}h->name[0]='\0'; /*把表头结点的数据域置空*/h->link=NULL; /*把表头结点的链域置空*/p=h; /*p指向表头结点*/for(i=0;i<n;i++){if((s= (stud *) malloc(sizeof(stud)))==NULL) /*分配新存储空间并检测*/{printf("不能分配内存空间!");exit(0);}p->link=s; /*把s的地址赋给p所指向的结点的链域,这样就把p和s所指向的结点连接起来了*/ printf("请输入第%d个人的姓名",i+1);scanf("%s",s->name); /*在当前结点s的数据域中存储姓名*/s->link=NULL;p=s;}return(h);}main(){int number; /*保存人数的变量*/stud *head; /*head是保存单链表的表头结点地址的指针*/number=N;head=creat(number); /*把所新建的单链表表头地址赋给head*/}这样就写好了一个可以建立包含N个人姓名的单链表了。

写动态内存分配的程序应注意,请尽量对分配是否成功进行检测。

二、单链表的基本运算建立了一个单链表之后,如果要进行一些如插入、删除等操作该怎么办?所以还须掌握一些单链表的基本算法,来实现这些操作。

单链表的基本运算包括:查找、插入和删除。

下面我们就一一介绍这三种基本运算的算法,并结合我们建立单链表的例子写出相应的程序。

1、查找对单链表进行查找的思路为:对单链表的结点依次扫描,检测其数据域是否是我们所要查好的值,若是返回该结点的指针,否则返回NULL。

因为在单链表的链域中包含了后继结点的存储地址,所以当我们实现的时候,只要知道该单链表的头指针,即可依次对每个结点的数据域进行检测。

以下是应用查找算法的一个例子:#include <stdio.h>#include <malloc.h>#include <string.h> /*包含一些字符串处理函数的头文件*/#define N 10typedef struct node{char name[20];struct node *link;}stud;stud * creat(int n) /*建立链表的函数*/{stud *p,*h,*s;int i;if((h=(stud *)malloc(sizeof(stud)))==NULL){printf("不能分配内存空间!");exit(0);}h->name[0]='\0';h->link=NULL;p=h;for(i=0;i<n;i++){if((s= (stud *) malloc(sizeof(stud)))==NULL){printf("不能分配内存空间!");exit(0);}p->link=s;printf("请输入第%d个人的姓名",i+1);scanf("%s",s->name);s->link=NULL;p=s;}return(h);}stud * search(stud *h,char *x) /*查找链表的函数,其中h指针是链表的表头指针,x指针是要查找的人的姓名*/{stud *p; /*当前指针,指向要与所查找的姓名比较的结点*/char *y; /*保存结点数据域内姓名的指针*/p=h->link;while(p!=NULL){y=p->name;if(strcmp(y,x)==0) /*把数据域里的姓名与所要查找的姓名比较,若相同则返回0,即条件成立*/return(p); /*返回与所要查找结点的地址*/else p=p->link;}if(p==NULL)printf("没有查找到该数据!");}main(){int number;char fullname[20];stud *head,*searchpoint; /*head是表头指针,searchpoint是保存符合条件的结点地址的指针*/ number=N;head=creat(number);printf("请输入你要查找的人的姓名:");scanf("%s",fullname);searchpoint=search(head,fullname); /*调用查找函数,并把结果赋给searchpoint指针*/}。

相关文档
最新文档