C/C++ 单链表的基本操作

数据结构-----C/C++实现 专栏收录该内容
9 篇文章 0 订阅

话不多说,直接上代码:
头文件LinkList.h

#ifndef LINKLIST_H_INCLUDED
#define LINKLIST_H_INCLUDED
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef struct node{
	int data;
	struct node *next;
}LNode, *LinkList;

//初始化一个带头结点的空链表
LinkList InitLinkList();
//遍历链表
void traverse_list(LinkList L);
//头插法建立链表,每次在表头插入
LinkList CreateList_byhead(LNode *L);
//尾插法建立链表
void CreateList_bytail(LinkList &L);
//求链表长度
int LinkLen(LNode *L);
//按值查找操作,返回节点指针
LinkList LocateElem(LNode *L, int key);
//找到第i个位置的节点并返回节点指针
LinkList GetElem(LinkList L,int i);
//删除结点
LinkList ListDelete(LNode *L, int &e);
//链表倒置
LinkList ReverseList(LinkList L);
//链表排序(冒泡排序)
void BubbleSort(LinkList &L);
//删除链表中的绝对值相同的节点
void FiltrateRep(LinkList &L);
#endif // LINKLIST_H_INCLUDED

具体的函数实现LinkList.cpp


#include"LinkList.h"
//初始化一个空链表
LinkList InitLinkList()
{
	LinkList head = (LinkList)malloc(sizeof(LNode));
	head->data = 0;//初始化数字域
	head->next = NULL;//初始化指针域

	return head;
}
//遍历链表
void Traverse_list(LinkList L)
{
	LinkList p = L->next;                            //将第一个节点的指针给予临时节点p
	while (NULL != p)                                //节点p不为空,循环
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
	return;
}

//头插法建立链表,每次在表头插入
LinkList CreateList_byhead(LNode *L)
{
    int val,len,a=0;
	cout<<"头插法建立链表,请输入节点数: ";
	cin>>len;
	while(a<len)
    {

        cout<<"第"<<++a<<"个节点的数值:";
        cin>>val;
        LinkList newNode = (LinkList)malloc(sizeof(LNode));
        newNode->data = val;
        newNode->next = L->next;
        L->next = newNode;
    }
	return L;
}
//尾插法建立链表
void CreateList_bytail(LinkList &L)
{
    int val,len;
    LinkList newNode = (LinkList)malloc(sizeof(node));
    LinkList tmp = L;
    cout<<"尾插法建立链表,请输入节点数: ";
    cin>>len;
    for(int i=0;i<len;i++)
    {
        cout<<"第"<<i+1<<"个节点的数值:";
        cin>>val;
        newNode->data = val;
        newNode->next = NULL;
        tmp->next = newNode;
        tmp = newNode;
    }
    L->data = len;            //头结点记录链表长度
}
//求链表长度
int LinkLen(LNode *L)
{
	int len = 0;
	LNode *ptmp = L->next;

	while (ptmp != NULL)
	{
		len++;
		ptmp = ptmp->next;
	}

	return len;
}
//按值查找操作
LinkList LocateElem(LNode *L,int key)
{
	LNode *ptmp = L->next;
	while (ptmp->data != key && ptmp->next != NULL)
		ptmp = ptmp->next;
    return ptmp;                  //找到后返回值为key的节点指针,否则为NULL
}
//按序号查找第i个节点
LinkList GetElem(LinkList L,int i)
{
    int j=1;
    LinkList p = L->next;
    if(i==0)
        return L;     //返回头结点
    if(i>LinkLen(L)||i<0)
        return NULL;      //i无效

    while(p&&j<i)
    {
        p = p->next;
        j++;
    }
    return p;
}
//在第i个位置上插入新节点
LinkList ListInsert(LNode *L,int val,int i)
{
	LNode *pnode = (LinkList)malloc(sizeof(LNode));//初始化插入的结点
	pnode->data = val;
	LNode *ptmp = GetElem(L,i-1);//查找到第i-1个结点

	if (ptmp == NULL)//链表为空,或者没有找到
	{
		printf("Link is empty or not found key!\n");
		return L;
	}
	else//将新结点插入第i-1个节点的后面
	{
		pnode->next = ptmp->next;
		ptmp->next = pnode;
	}

	return L;
}

//删除结点
bool ListDelete(LinkList &L, int i,int &e)
{
	LNode *ptmp ;
	LNode *tmp;

	if (L == NULL)//处理链表为空的情况
	{
		printf("Link is empty,delete fail!\n");
		return false;
	}
	if(i<=LinkLen(L))
	{

        ptmp = GetElem(L,i-1);
	    tmp = GetElem(L,i);
	    e = tmp->data;
	    ptmp->next = tmp->next;
	    free(tmp);
	    return true;
	}
}
//链表倒置
//链表的倒置算法思路:一次取出原链表中的每一个结点,将
//其作为第一个结点前插法插入新链表中。
//逆序输出链表中的元素,基本算法还可以使用一个辅助空间栈,
//先遍历一边单链表,把元素存在栈中,然后输出栈中的元素。
LinkList ReverseList(LinkList L)
{
	LNode *ptmp = (LinkList)malloc(sizeof(LNode));//创建一个新链表
	ptmp->next = NULL;
	LNode *tmp = NULL;

	if (L ->next== NULL)
	{
		printf("list is empty!\n");
		return NULL;
	}
	else
	{
	    L = L->next;
		while (L != NULL)//将链上的结点链到新链上
		{

            tmp = L;
            L = L->next;
			tmp->next = ptmp->next ;
			ptmp->next = tmp;
		}
	}

	return ptmp;

}
 //链表排序(冒泡排序)
void BubbleSort(LinkList &L)
{
	LNode *p = NULL;//i
	LNode *q = L;//j
	LNode *r = L;
	int tmp;

	for (p = L->next; p; p = p->next)
	{
	    r = p;
		for (q = p->next; q; q = q->next)
		{
			if (p->data > q->data)
			{
				tmp = p->data;
				p->data = q->data;
				q->data = tmp;
				r = r->next;
			}
		}
	}
}

主函数List_main.cpp,测试使用

#include"LinkList.h"
#include"LinkList.cpp"
#include"FiltrateRep.cpp"
//主函数
int main()
{
    int e;
	LinkList L = InitLinkList();
	L= CreateList_byhead(L);

	printf("遍历链表:\n");
	Traverse_list(L);

	//bool l = ListDelete(L,2,e);
	//cout<<e;

	//LinkList L1 = ReverseList(L);
	//Traverse_list(L1);
	BubbleSort(L);
	Traverse_list(L);
	return 0;
}

FiltrateRep.cpp

#include"LinkList.h"
#include<string.h>
/*
问题描述:删除单链表中绝对值重复的元素。如:(21,-15,-15,-7,15)->(21,-15,-7)
说明:其实这题比较好的思路还是以前说的,以空间换时间。还是以前说的分类,把归属于一类的当成一种情况
(这里是绝对值相同的元素),看它们能不能有相同的容易被检测到操作,在这里是把辅助数组对应位置加1。
这样的话,遍历一遍就可以完成问题,时间复杂度是O(N),普通的算法,来回重复遍历,复杂度是O(N2)。
不过还是老问题,这里需要元素的绝对值的最大值不能太大因为这是辅助数组是根据元素绝对值的最大值申请空间的。

*/

const int MAXSIZE = 20;

//筛选链表中绝对值重复的元素
void FiltrateRep(LinkList &L)
{
    int temp[MAXSIZE];      //辅助元素

    memset(temp,0,sizeof(int)*MAXSIZE);     //初始化为0

    LNode *pre = NULL,*p =NULL ;

    pre = L;
    while(pre->next != NULL)
    {
        p = pre->next;

        if( p!= NULL)
        {
             if(temp[abs(p->data)] < 1)
             {
                  ++temp[abs(p->data)];        //辅助数组对应元素位置+1
                  pre = p;                      //由指向头节点的指针不断后移
             }
             else       //如果temp[p->data]大于1,正在判断的元素,是重复元素,需要删除
             {
                 pre->next = p->next;   //删除重复的元素

                 free(p);
             }
        }
    }
}


  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值