C++设计单链表习题及解答

C++设计单链表习题及解答

题目:实现一个单链表,链表初始为空,支持三种操作:

  • 向链表头插入一个数
  • 删除第 k 个插入的数后面的数;
  • 在第 k 个插入的数后插入一个数

(不知道这里题目有没有理解错,我理解的是删除第k个插入的数(x),x的指针next所指向的数,即删除第k-1个插入的数)

第一版源代码:

#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct ListNode
{
	int data;//数据域 
	struct ListNode*next;//指针域 
}*L;//相当于typedef struct ListNode*L; 
//创建节点 
void CreateListNode(L*head) //改变链表的操作要用指针传链表 ,也可以不用void,而用指针类型的函数 L CreateListNode(L head){...return head;},这里只是想麻烦地练练手,嘻嘻
{
  		*head = (ListNode *)malloc(sizeof(ListNode));   //创建头结点,为头结点分配内存 
        (*head)->next = NULL;//初始化头结点的指针head为空指针 
}
//向链表头插入一个数
void addAtHead(L*head,int val) 
{
	L newhead=(ListNode *)malloc(sizeof(ListNode));//创建新的头结点,为新的头结点分配内存
	 newhead->next=(*head)->next;
     (*head)->next=newhead;
     newhead->data=val;
} 
//删除第 k 个插入的数后面的数
 void deleteAtIndex(L*head,int k)
{
    L cur=*head;//辅助指针从第一个节点开始
    while(k--)//遍历到第k个位置(非下标),循环次数是k次
	{
        cur=cur->next;
    }
    L p=cur->next;
	if(cur->next->next!=NULL)
    cur->next = cur->next->next; 
    else cur->next=NULL;
	free(p);
}
//在第 k 个插入的数后插入一个数
void addAtIndex(L*head,int k,int val) 
{
    L newnode=(ListNode *)malloc(sizeof(ListNode));
    L cur=*head;//辅助指针从头指针开始
    while(k--) cur=cur->next;//遍历到第k个节点(非下标),循环次数是k次 
    newnode->next=cur->next;
    cur->next=newnode;
    newnode->data=val;
}
//打印出链表形态 
void printlist(L head)
{
	L newnode=head->next;
	while(newnode!=NULL)
	{
		cout<<newnode->data;
		if(newnode->next!=NULL)cout<<"->";
		newnode=newnode->next;
	}
	cout<<endl;
}
int main()
{
	L head;
	CreateListNode(&head);
	int n,x1,k,x2;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>x1;
		addAtHead(&head,x1);
	}
	cin>>k;
	cin>>x2;
	cout<<"n="<<n<<"  k="<<k<<endl;
	cout<<"操作一,输入n,每次向链表头插入一个数,共插入n个数:" ; 
	printlist(head);
	deleteAtIndex(&head,n-k+1);
	cout<<"操作二,输入k删,除第 k (1<k<=n)个插入的数后面的一个数:";
	printlist(head);
	cout<<"操作三,在第 k (1<k<=n)个插入的数后插入一个数:";
	addAtIndex(&head,n-k+1,x2);
	printlist(head);
	return 0;
}

运行结果:
在这里插入图片描述

写完才发现,好像混用了C和C++(心痛的感觉),于是经过一番折腾,又诞生了第二版题解
改进:
①引用了C++的struct中特有的构造函数(C没有)
②采用类class
③把malloc换成new
其它一样
第二版源代码:

#include<iostream>
using namespace std;
typedef struct ListNode
{
    int data;
    struct ListNode *next;
    ListNode(int x) : data(x), next(NULL) {}//有参数构造函数,就是初始化, 注意:若要初始化数组,需先写无参数构造函数 
}*L;
class MyLinkedList
{
private://private在其他类中被隐藏 
    L head; 
public://把public的函数写在class外更为清晰明了
	CreateListNode(); 
	void addAtHead(int val);
	void addAtIndex(int k, int val);
	void deleteAtIndex(int k);
	void printlist();
};//被漏掉的分号(尴尬) 
    MyLinkedList::CreateListNode()
	{
        head=new ListNode(0);//不能在private内初始化
    } 
    void MyLinkedList::addAtHead(int val)
	{
    	L newhead=new ListNode(val);//new是堆中的内存块,与之前的malloc作用相同 
		newhead->next=head->next;
     	head->next=newhead;
     	newhead->data=val;
    } 
    
    void MyLinkedList::addAtIndex(int k, int val)
	{
        L newnode=new ListNode(val);
	    L cur=head;
	    while(k--) cur=cur->next;
	    newnode->next=cur->next;
	    cur->next=newnode;
	    newnode->data=val;
    }
    
    void MyLinkedList::deleteAtIndex(int k)
	{
        L cur=head;
	    while(k--)
		{
	        cur=cur->next;
	    }
	    L p=cur->next;
		if(cur->next->next!=NULL)
	    cur->next = cur->next->next; 
	    else cur->next=NULL;
		delete p;//与之前的free作用相同 ,new分配的内存块由程序员释放(编译器不管) ,所以也要回收 
    }
    void MyLinkedList::printlist()
	{
		L newnode=head->next;
		while(newnode!=NULL)
		{
			cout<<newnode->data;
			if(newnode->next!=NULL)cout<<"->";
			newnode=newnode->next;
		}
		cout<<endl;
	}
int main()
{
	MyLinkedList object;//MyLinkedList类里的object成员
	object.CreateListNode();
	int n,x1,k,x2;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>x1;
		object.addAtHead(x1);
	}
	cin>>k;
	cin>>x2;
	cout<<"n="<<n<<"  k="<<k<<endl;
	cout<<"操作一,输入n,每次向链表头插入一个数,共插入n个数:" ; 
	object.printlist();
	object.deleteAtIndex(n-k+1);
	cout<<"操作二,输入k删,除第 k (1<k<=n)个插入的数后面的一个数:";
	object.printlist();
	cout<<"操作三,在第 k(1<k<=n) 个插入的数后插入一个数:";
	object.addAtIndex(n-k+1,x2);
	object.printlist();
	return 0;
}

运行结果:(和之前一样)
在这里插入图片描述
学习心得:刚开始写的时候还不知道头结点(不是第一个节点)的好处,写着写着才发现如果不设头指针,链表开始的位置在每一次addAtHead的时候都得改,这样较为方便

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值