C语言单链表代码实现

本文详细介绍了如何使用C语言设计算法,包括单链表的创建、元素操作(查找、插入、删除),以及链表转换为循环链表、有序表插入、元素逆置和两个有序表的合并。
摘要由CSDN通过智能技术生成

声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

设计算法,实现线性结构上的单链表的产生以及元素的查找、插入与删除,求表长、有序表插入、元素逆置、2个有序表合并等。

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

//单链表的定义:
typedef int DataType;		//DataType可以是任何相应的数据类型如int, float或char

typedef struct ListNode			//结点类型定义
{	DataType data;			//结点的数据域
	struct ListNode *next;		//结点的指针域
}ListNode;

typedef ListNode *LinkList;
//测试用例		1 2 3 4 5 6 7 8 9 10 -1
			//	4 6 8 10 12 -1
int main()
{
	int i,j;
	DataType key,x;
	LinkList head=NULL;

	LinkList CreateList();
	void PrintList(LinkList head);
	int LocateNode(LinkList head,DataType key);
	void InsertList(LinkList head,DataType x,int i);
	void DeleteList(LinkList head,int i);
    void ChangeCircList(LinkList head);
	void PrintCircList(LinkList head);
	void InsertOrderList(LinkList head,int x);
	LinkList reverseList(LinkList head);
	void MergeList_L(LinkList La,LinkList Lb,LinkList *Lc);

	char choice;
	while (1)
	{
		system("cls");
		printf("\n\n\n\n");
		printf("\t\t              链表操作  \n");
		printf("\t\t======================================");
		printf("\n\n");
		printf("\t\t             1:建立单链表            \n");
		printf("\t\t             2:显示单链表            \n");
		printf("\t\t             3:查找                  \n");
		printf("\t\t             4:插入                  \n");
		printf("\t\t             5:删除                  \n");
        printf("\t\t             6:改为循环单链表并显示  \n");
        printf("\t\t             7:有序表插入            \n");
        printf("\t\t             8:元素逆置              \n");
        printf("\t\t             9:2个有序表合并         \n");
		printf("\n");
		printf("\t\t             0:退出        \n");
		printf("\n");
		printf("\t\t请选择:");

		choice = getchar();
		system("cls");

		switch(choice)
		{
			case '1':
				printf("输入单链表:");
				head=CreateList();
				printf("链表创建成功!\n");
				getchar();/*第一个getchar会接收到上面createList函数中scanf最后敲击的回车
所以后面再加一个,这样系统才会等待下一个字符进入,才能看得到东西 */
				getchar();
				break;
			case '2':
				PrintList(head);
				getchar();
                getchar();
				break;
			case '3':
		        printf("输入要查找的值:");
            	scanf("%d",&key);
            	j=LocateNode(head,key);	//单链表查找
				printf("要查找的值在第%d个\n",j);
				getchar();
				getchar();
				break;
			case '4':
				printf("请输入欲插入元素的位置:");
	            scanf("%d",&i);
             	printf("请输入欲插入的元素:");
	            scanf("%d",&x);
	            InsertList(head,x,i);	//单链表插入
	            PrintList(head);			//输出顺序表
				getchar();
				getchar();
				break;
			case '5':
				printf("请输入欲删除结点的位置:");
	            scanf("%d",&i);
	            DeleteList(head,i);		//单链表删除
	            PrintList(head);			//输出顺序表
				getchar();
				getchar();
				break;
			case '6':
                ChangeCircList(head);	//修改为循环单链表
                printf("改为循环单链表成功:\n");
				PrintCircList(head);	//输出循环单链表
				getchar();
				getchar();

				break;
			case '7':
				printf("请输入欲插入有序表的元素:");
	            scanf("%d",&x);
				InsertOrderList(head,x);
				PrintList(head);
				getchar();
				getchar();
				break;
			case '8':
				head=reverseList(head);
				printf("逆置成功\n");
				PrintList(head);
				getchar();
				getchar();
				break;
			case '9':
				printf("输入要被合并的顺序表:");
				LinkList Lb;
				LinkList Lc;
				Lb=CreateList();
				printf("链表创建成功!\n");
				MergeList_L(head,Lb,&Lc);
				printf("顺序表合并成功!\n");
				PrintList(Lc);
				getchar();
				getchar();
				break;
			case '0':
				exit(0);
		}
	}
}

LinkList CreateList()
{
    int num;
    int head_data;
    struct ListNode *s, *r, *h = (struct ListNode *)malloc(sizeof(struct ListNode));
    scanf("%d", &head_data);
    h->data = head_data;
    r = h; /* 尾指针初值指向头结点 */
    scanf("%d", &num);
    while (num != -1)
    {
        s = (struct ListNode *)malloc(sizeof(struct ListNode)); /* 生成新结点*/
        if (s == NULL)
        {
            printf("内存分配失败\n");
            exit(-1);
        }
        s->data = num;
        r->next = s;

        r = s;
        scanf("%d", &num); // 更新输入的 num 值
    }
    r->next = NULL;
    return h; /* 返回头指针 */
}

//单链表的输出:
void PrintList(LinkList head)
{
	int c=0;
    LinkList cur;
    if (head != NULL)
        cur = head;
    else{
        printf("no node");
        return;
    };
	while (cur != NULL){
        printf("%d ", cur->data);
        c++;
        cur = cur->next;
	}
	printf("\n现在表长为:%d", c);
	return;

}

//单链表的查找:
int LocateNode(LinkList head,DataType key)
{
	int c=1;
	ListNode *p=head;//->next; /* 从开始结点比较 */
 	while (p&&p->data!=key){ /* 直到 p 为 NULL 或 p->data 是 key为止 */
 	p=p->next; /* 扫描下一结点 */
 	c++;}
 	return c;
}

//单链表的插入:
void InsertList(LinkList head,DataType x,int i)
{
	ListNode *p=head,*s;
	int j=0;
	int c=2;/* 寻找第 i-1 个结点 */
 	while (p&&c<i){ /* 直到 p 为 NULL 或 p->data 是 key为止 */
 	p=p->next; /* 扫描下一结点 */
 	c++;
	 }
if(p==NULL){
printf(" 插入位置非法 \n");
exit(0);
}
s=(LinkList)malloc(sizeof(ListNode));
s->data=x;
s->next=p->next;
 p->next=s;
}

//单链表的删除:
void DeleteList(LinkList head,int i)
{
	 ListNode *p=head,*q;
 int c=2;/* 寻找第 i-1 个结点 */
 	while (p&&c<i){ /* 直到 p 为 NULL 或 p->data 是 key为止 */
 	p=p->next; /* 扫描下一结点 */
 	c++;
	 }
 if(p==NULL||p->next==NULL){
 printf(" 删除位置非法 \n");
 exit(0);
 }
 q=p->next; // 临时保存被删结点的地址以备释放
 p->next=q->next; // 改变删除结点前驱结点的指针域

 free(q); // 释放删除结点的空间
}


//修改为循环单链表:
void ChangeCircList(LinkList head)
{
	ListNode *p=head;//->next; /* 从开始结点比较 */
 	while (p->next)/* 直到 p->next 为 NULL是 key为止 */
 	p=p->next; /* 扫描下一结点 */
 	p->next=head;

}


//循环单链表的输出:
void PrintCircList(LinkList head)
{
	LinkList cur;
	int c=0;
    if (head != NULL)
        cur = head;
    else{
        printf("no node");
        return;
    };
	while (cur->next != head){
        printf("%d ", cur->data);
        cur = cur->next;
        c++;
	}

	printf("%d ", cur->data);
	c++;
	printf("\n现在表长为:%d ", c);
	return;
}

void InsertOrderList(LinkList head,int x)
{
	ListNode *p=head,*s;
	int j=0;
 	while (p->data<x){
 	p=p->next; /* 扫描下一结点 */
  }
s=(LinkList)malloc(sizeof(ListNode));
s->data=x;
s->next=p->next;
 p->next=s;
}

LinkList reverseList(LinkList head)
{
	if (head == NULL || head->next == NULL) {
        return head;
    }
    // 例:1->2->3->4->5-null,从 if 递归出口返回时 newHead = 5, head = 4(递归特点:谁调用返回给谁)
    LinkList newHead =reverseList(head->next);
    // head = 4, newHead = 5, head.next.next = 4.next.next = 5.next = 4
    head->next->next = head;
    // 避免链表成环,5->4->null
    head->next = NULL;
    // 返回新的头节点
   	return newHead;
}


void MergeList_L(LinkList La, LinkList Lb, LinkList *Lc) { // 修改参数类型,
    LinkList pa = La;
    LinkList pb = Lb;
    LinkList pc;

    if (La->data < Lb->data) {
        pc = La;
        *Lc = La;
        pa = La->next;
    } else {
        pc = Lb;
        *Lc = Lb;
        pb = Lb->next;
    }

    while (pa && pb) {
        if (pa->data <= pb->data) {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        } else {
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }

    pc->next = pa != NULL ? pa : pb; // 插入剩余段
    //free(Lb);
}
四、运行输出结果:
LinkList CreateList();
输入单链表:1 2 3 4 5 6 7 8 9 10 -1
链表创建成功!
	void PrintList(LinkList head);
1 2 3 4 5 6 7 8 9 10
现在表长为:10
	int LocateNode(LinkList head,DataType key);
输入要查找的值:5
要查找的值在第5个
	void InsertList(LinkList head,DataType x,int i);
请输入欲插入元素的位置:2
请输入欲插入的元素:4
1 4 2 3 4 5 6 7 8 9 10
现在表长为:11
	void DeleteList(LinkList head,int i);
请输入欲删除结点的位置:2
1 2 3 4 5 6 7 8 9 10
现在表长为:10
void ChangeCircList(LinkList head);void PrintCircList(LinkList head);
改为循环单链表成功:
1 2 3 4 5 6 7 8 9 10
现在表长为:10
	void InsertOrderList(LinkList head,int x);
请输入欲插入有序表的元素:4
1 2 3 4 4 5 6 7 8 9 10
现在表长为:11
	LinkList reverseList(LinkList head);
逆置成功
10 9 8 7 6 5 4 3 2 1
现在表长为:10
	void MergeList_L(LinkList La,LinkList Lb,LinkList *Lc);
输入要被合并的顺序表:4 6 8 10 12 -1
链表创建成功!
顺序表合并成功!
1 2 3 4 4 5 6 6 7 8 8 9 10 10 12
现在表长为:15

运行输出结果:

LinkList CreateList();

输入单链表:1 2 3 4 5 6 7 8 9 10 -1

链表创建成功!

void PrintList(LinkList head);

1 2 3 4 5 6 7 8 9 10

现在表长为:10

int LocateNode(LinkList head,DataType key);

输入要查找的值:5

要查找的值在第5个

void InsertList(LinkList head,DataType x,int i);

请输入欲插入元素的位置:2

请输入欲插入的元素:4

1 4 2 3 4 5 6 7 8 9 10

现在表长为:11

void DeleteList(LinkList head,int i);

请输入欲删除结点的位置:2

1 2 3 4 5 6 7 8 9 10

现在表长为:10

void ChangeCircList(LinkList head);void PrintCircList(LinkList head);

改为循环单链表成功:

1 2 3 4 5 6 7 8 9 10

现在表长为:10

void InsertOrderList(LinkList head,int x);

请输入欲插入有序表的元素:4

1 2 3 4 4 5 6 7 8 9 10

现在表长为:11

LinkList reverseList(LinkList head);

逆置成功

10 9 8 7 6 5 4 3 2 1

现在表长为:10

void MergeList_L(LinkList La,LinkList Lb,LinkList *Lc);

输入要被合并的顺序表:4 6 8 10 12 -1

链表创建成功!

顺序表合并成功!

1 2 3 4 4 5 6 6 7 8 8 9 10 10 12

现在表长为:15

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值