单链表(创建<14种功能>,逆序,合并)

本文详细介绍了一个简单的单链表数据结构的实现方法,包括创建、遍历、插入、删除等核心操作,并提供了完整的C语言代码示例。此外,还介绍了如何通过递归或循环方式实现链表的逆序,以及有序链表的合并方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>
//结点的数据类型
typedef struct Node{
int data;
struct Node*next;
}Node;
//链表类型
typedef struct List{
Node *head;
}List;
//1创建节点
Node* CreateNode(int data){
Node* PtrNode=malloc(sizeof(Node));
PtrNode->data=data;
PtrNode->next=NULL;
return PtrNode;
}
//2向头结点位置插入新结点
void PushHead(List *list,int data){
Node*PtrNew=CreateNode(data);
PtrNew->next=list->head;//如果链表有节点  list->head是一个节点的地址 
list->head=PtrNew;//如果链表中无节点
}
//3.1遍历链表 参数为List* 型
void tralve(List*list){
printf("链表中的元素为:");
Node *PtrHead=list->head;//操作时指针指向可能发生变化 
if(!PtrHead){
puts("空");
}
while(PtrHead){
printf("%d ",PtrHead->data);
PtrHead=PtrHead->next;
}
printf("\n");
}
//3.1遍历链表 参数为Node* 型
void tralveNode(Node*head){
printf("链表中的元素为:");
Node *PtrHead=head;//操作时指针指向可能发生变化 
if(!PtrHead){
puts("空");
}
while(PtrHead){
printf("%d ",PtrHead->data);
PtrHead=PtrHead->next;
}
printf("\n");
}
//4 计算结点个数 
int length(List*list){
int count =0;
Node *PtrHead=list->head;
while(PtrHead){
count++;
PtrHead=PtrHead->next;
}
return count;
}
//5 向指定的位置插入数据
int insert(List*list, int position,int data){//position 0 1 2 3 4 ...
if(position<0||position>length(list)){
printf("插入位置不合法系统将默认向头节点插入\n");
position=0;
}
Node*PtrNew=CreateNode(data);
if(0==position){
PtrNew->next=list->head;
list->head=PtrNew;
return 0;
}
Node*PtrHead=list->head;
int i;
for(i=0;i<position-1;i++){
PtrHead=PtrHead->next;
}
PtrNew->next=PtrHead->next;
PtrHead->next=PtrNew;
}
//6 向尾部插入
void PushTail(List *list,int data){
insert(list,length(list),data);
}
//7删除指定的位置的结点
int delete(List *list,int position){
if(position<0||position>length(list)){
printf("坐标不合法 删除失败\n");
return 0;
}
if(0==position){
Node*PtrHead=list->head;
list->head=list->head->next;
free(PtrHead);
PtrHead=NULL;
return 0;
}
int i=0;
Node*PtrHead=list->head;
for(i=0;i<position-1;i++){
PtrHead=PtrHead->next;
}
Node*PtrTemp=PtrHead->next;
PtrHead->next=PtrTemp->next;
free(PtrTemp);
PtrTemp=NULL;
}
//8删除头结点
void PopHead(List*list){
delete(list,0);
}
//9删除尾结点
void PopTail(List*list){
delete(list,length(list)-1);
}
//10 判空
int empty(List*list){
return list->head==NULL;
}
//11 获取头结点
int GetHead(List*list){
if(!empty(list)){
return list->head->data;
}
return -1;
}
//12 获取尾结点
int GetTail(List *list){
if(!empty(list)){
Node*PtrHead=list->head;
while(PtrHead->next!=NULL){
PtrHead=PtrHead->next;
}
return PtrHead->data;
}
return -1;
}
//13 获取任意位置
void GetElement(List*list,int position){
printf("位置%2d的元素为:",position);
int i;
Node*PtrHead=list->head;
for(i=0;i<position;i++){
PtrHead=PtrHead->next;
}
printf("%d\n",PtrHead->data);
}
//14 销毁链表
void DetroyList(List*list){
while(list->head!=NULL){
Node*PtrHead=list->head->next;//存放所删除元素的next的值 也就是所要删除元素的下一个结点的地址 
free(list->head);
list->head=PtrHead;
}
printf("销毁链表完成\n");
}
//15 链表逆序(循环)
Node*ReverseList1(Node*Ptr){
if((Ptr==NULL)||(Ptr->next==NULL))
return NULL;
Node*Prev =NULL;
Node*Current = Ptr;//1定位
Node*Pnext =NULL;
while(Current){//2备份3逆向4前(prev)移,前移(current)
Pnext = Current->next;//2准备工作:为向后遍历正常进行,先把Current->next存到pnext里 下面current->next会改变指向
Current->next=Prev;//3当前的next指向当前结点的前结点(第一次是current->next指向空(同时也把原头指针置空),第二次就是当前结点的前结点(prev=current首结点))
Prev = Current;//三个临时指针变量向前
Current = Pnext;//当前位置向前移动 重复操作
}
return Prev;//原来的尾结点变成新首结点
}
//16 链表逆序(递归)
 Node* ReverseList2(Node *Ptr){
     if ((Ptr->next == NULL)||(Ptr==NULL))
        return Ptr;
Node*NewHead=ReverseList2(Ptr->next);/*递归 后续结点*/
Ptr->next->next=Ptr;/*回溯 ,被 摘除的首结点要被连接到ptr->next才能完成逆序 后续结点的next(也就是后续元素逆序完后的尾结点要指向前面被拆分的结点) 指向前结点*/
Ptr->next=NULL;//取消正向指针 不然形成了环形
return NewHead;
}
//17 链表(有序)合并
Node *Merge(Node *head1,Node *head2){
    Node *p1 = NULL;
    Node *p2 = NULL;
    Node *head = NULL; //找出两个链表中第一个结点较小的结点,head记录较小结点的头结点
    if(head1->data < head2->data){
printf("%d   %d\n",head1->data,head2->data);
        head = head1;
        p1 = head1->next;//下一个位置
        p2 = head2;
    }
    else{
        head = head2;
        p2 = head2->next;
        p1 = head1;
    }
    Node *pcur = head;
printf("%d\n",pcur->data);//1
    //在两个链表中遍历比较,将值较小的结点链接到pcur结点后
    while(p1!= NULL && p2 != NULL){
        if(p1->data <= p2->data){
            pcur->next = p1;
            pcur = p1;
            p1 = p1->next;
        }
        else{
            pcur->next = p2;
            pcur = p2;
            p2 = p2->next;
        }
    }
    //将p1或p2剩余的结点链到pcur之后,完成整个合并的过程
    if(p1 != NULL)
        pcur->next = p1;
    if(p2 != NULL)
        pcur->next = p2;
    return head;
}
int main(){
/*List list;
list.head=NULL;//头指针
PushHead(&list,1);
tralve(&list);
PushHead(&list,2);
tralve(&list);
PushHead(&list,3);
tralve(&list);
// list.head=ReverseList1(list.head);
list.head=ReverseList2(list.head);
tralve(&list);*/
//-------------调试逆序功能
List list2;
list2.head=NULL;//头指针
PushHead(&list2,3);
PushHead(&list2,2);
PushHead(&list2,1);
tralve(&list2);
Node*newhead2 = ReverseList1(list2.head);
tralveNode(newhead2);
Node*newhead22 = ReverseList1(newhead2);
tralveNode(newhead22);
Node*newhead222 = ReverseList2(newhead22);
tralveNode(newhead222);
Node*newhead2222 = ReverseList2(newhead222);
tralveNode(newhead2222);
//----------------------
List list3;
list3.head=NULL;//头指针
PushHead(&list3,9);
PushHead(&list3,8);
PushHead(&list3,7);
tralve(&list3);
List list4;
list4.head = Merge(list2.head,list3.head);
Node*new = list4.head;
tralveNode(new);
/*Node *ptr;
    ptr = Merge(list2.head,list3.head);
    ptr = ptr->next;
    while(ptr != NULL)
    {
        printf("%d ",ptr->data);
        ptr = ptr->next;
    }
    printf("\n");
/*Node*pNode=ReverseList2(ptr);
 while(pNode != NULL)
    {
        printf("%d ",pNode->data);
        pNode = pNode->next;
    }*/
  //  printf("/n");
// tralve(&list4);//这样遍历少了第二组的首结点的值
/*p= p->next;
list4.head = p;
tralve(&list4);*/
/*printf("lenght=%d\n",length(&list));
insert(&list,1,33);
tralve(&list);
PushTail(&list,11);
tralve(&list);
delete(&list,4);
tralve(&list);
delete(&list,1);
tralve(&list);
PopHead(&list);
tralve(&list);
PopTail(&list);
tralve(&list);
PushHead(&list,3);
tralve(&list);
PushTail(&list,1);
tralve(&list);
printf("%s\n",empty(&list)?"链表为空":"链表非空");
printf("头结点元素为:%d\n",GetHead(&list));
printf("尾结点元素为:%d\n",GetTail(&list));
GetElement(&list,0);
GetElement(&list,1);
GetElement(&list,2);
DetroyList(&list);
tralve(&list);*/
return 0;
}
//整个程序禁止使用同名变量名//程序框架不要动//形参需不需要引用自行调整 using namespace std; #include<iostream> #include <string.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #define MAXSIZE 10 typedef struct{//定义数据元素结构体//至少有学号和成绩两个成员}istudent; typedef struct node[//定义链表结构体,参照书上定义}LNode.*LinkList; InitList(LinkList &L1){//新建带头结点空链表} InitValue(LinkList &L2){//用前插法插入学号4开始往后数,15位同学,要求链表中学号从小到大排列} GetElem(LinkList &L3,int i,ElemType e){//查找单链表L中第i个元素,如果查找成功,输出该元素信息,如果查找失败,输出“查找失败"} Listinsert(LinkList &L4,int i,ElemType e) {//单链表L中第i个元素位置之前插入数据元素e} int DeleteLinkList( LinkList &L5, int i) {//在链表中删除第i个结点} int show( LinkList &L6) {//输出所有链表数据} int DestroyList( LinkList &L7,int i){//释放链表中所有结点} //主程序,所有功能通过调用函数实现//定义一个链表变量//新建一个空链表 int main(){ //用前插法插入学生数据元素,//输出所有链表数据 //查找链表中第i(i=自己学号个位+5)个学生,输出该生的学号和成绩//查找链表中第25个学生,输出该生的信息;如查找不到,输出“查找失败,无第25个”//在第i(i=自己学号个位+3)个元素前插入一个元素(自己学号+15)同学//输出所有链表数据//删除链表中第i(i=自己学号个位+6)个元素//输出所有链表数据 //用free函数释放链表中所有结点的存储空间system("pause"); return 0; } 用C语言补充代码,完成注释要求
最新发布
03-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值