线性表-2 单链表

一:实现单链表各种基本运算的算法。

#include<stdio.h>
#include<malloc.h>
typedef char ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;			//指向后继结点
}LinkNode;						//声明单链表结点类型
void CreateListF(LinkNode*& L, ElemType a[], int n)		//头插法
{
	LinkNode* s;
	L = (LinkNode*)malloc(sizeof(LinkNode));		//创建头结点
	L->next = NULL;
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));	//创建新结点s
		s->data = a[i];
		s->next = L->next;		//将结点s插入原结点之前,头结点之后
		L->next = s;
	}
}
void CreateListR(LinkNode*& L, ElemType a[], int n)		//尾插法
{
	LinkNode* s, * r;
	L = (LinkNode*)malloc(sizeof(LinkNode));		//创建头结点
	L->next = NULL;
	r = L;							//r始终指向尾结点,开始时指向头结点
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));	//创建新结点s
		s->data = a[i];
		r->next = s;
		r = s;
	}
	r->next = NULL;					//尾结点的next域置为NULL
}
void InitList(LinkNode*& L)			//初始化线性表
{
	L = (LinkNode*)malloc(sizeof(LinkNode));		//创建头结点
	L->next = NULL;					//将单链表置为空表
}
void DestroyList(LinkNode*& L)		//销毁线性表
{
	LinkNode* pre = L, * p = pre->next;
	while (p != NULL)
	{
		free(p);
		pre = p;					//pre,p同步后移一个结点
		p = pre->next;
	}
	free(pre);			//此时p为NULL,pre指向尾结点,释放它
}
bool ListEmpty(LinkNode* L)			//判断线性表是否为空表
{
	return(L->next == NULL);
}
int ListLength(LinkNode* L)			//求线性表长度
{
	int i = 0;
	LinkNode* p = L;		//p指向头结点,i置为0(即头结点序号为0)
	while (p->next != NULL)
	{
		i++;
		p = p->next;
	}
	return(i);
}
void DispList(LinkNode* L)			//输出线性表
{
	LinkNode* p = L->next;			//p指向首结点
	while (p != NULL)				//p不为NULL,输出p的data域
	{
		printf("%c", p->data);
		p = p->next;				//p移向下一个结点
	}
	printf("\n");
}
bool GetElem(LinkNode* L, int i, ElemType& e)	//求线性表中第i个元素值
{
	int j = 0;
	LinkNode* p = L;		//p指向头结点,j置为0(即头结点序号为0)
	if (i <= 0)
		return false;		//i错误返回false
	while (j < i && p != NULL)		//找第i个结点p
	{
		j++;
		p = p->next;
	}
	if (p == NULL)			//不存在第i个结点,返回false
		return false;
	else                    //存在第i个结点,返回true
	{
		e = p->data;
		return true;
	}
}
int LocateElem(LinkNode* L, ElemType e)		//查找第一个值域为e的元素的序号
{
	int i = 1;
	LinkNode* p = L->next;			//p指向首结点,i置为1(即首结点序号为1)
	while (p != NULL && p->data != e)
	{
		p = p->next;
		i++;
	}
	if (p == NULL)			//不存在值为e的结点,返回0
		return (0);
	else                    //存在值为e的结点,返回逻辑序号1
		return(i);
}
bool ListInsert(LinkNode*& L, int i, ElemType e)	//插入第i个元素
{
	int  j = 0;
	LinkNode* p = L, * s;			//p指向头结点,j置为0(即头结点序号为0)
	if (i <= 0)						//i错误返回false
		return false;
	while (j < i - 1 && p != NULL)	//查找第i-1个结点p
	{
		j++;
		p = p->next;
	}
	if (p == NULL)				 //未找到i-1个结点p,返回false
		return false;
	else                         //找到i-1个结点p,插入新结点并返回true
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));  //创建新结点s,将其data域置为e
		s->data = e;
		s->next = p->next;            //将结点s插入结点p之后
		p->next = s;
		return true;
	}
}
bool ListDelete(LinkNode*& L, int i, ElemType& e)		//删除第i个元素
{
	int j = 0;
	LinkNode* p = L, * q;		//p指向头结点,j置为0(即头结点序号为0)
	if (i <= 0)					//i错误返回false
		return false;
	while (j < i - 1 && p != NULL)   //查找第i-1个结点
	{
		j++;
		p = p->next;
	}
	if (p == NULL)				//未找到i-1个结点,返回false
		return false;
	else                        //找到i-1个结点p
	{
		q = p->next;			//q指向第i个结点
		if (q == NULL)			//若不存在第i个结点,返回false
			return false;
		e = q->data;
		p->next = q->next;		//从单链表中删除q结点
		free(q);				//释放q结点
		return true;			//返回true表示成功删除第i个结点
	}
}
int main()
{
	LinkNode* h;
	ElemType e;
	printf("单链表的基本运算如下:\n");
	printf("  (1)初始化单链表h\n");
	InitList(h);
	printf("  (2)依次采用尾插法插入a,b,c,d,e元素\n");
	ListInsert(h, 1, 'a');
	ListInsert(h, 2, 'b');
	ListInsert(h, 3, 'c');
	ListInsert(h, 4, 'd');
	ListInsert(h, 5, 'e');
	printf("  (3)输出单链表h:");
	DispList(h);
	printf("  (4)单链表h长度:%d\n", ListLength(h));
	printf("  (5)单链表h为%s\n", (ListEmpty(h) ? "空" : "非空"));
	GetElem(h, 3, e);
	printf("  (6)单链表h的第3个元素:%c\n", e);
	printf("  (7)元素a的位置:%d\n", LocateElem(h, 'a'));
	printf("  (8)在第4个元素位置上插入f元素\n");
	ListInsert(h, 4, 'f');
	printf("  (9)输出单链表h:");
	DispList(h);
	printf("  (10)删除h的第3个元素\n");
	ListDelete(h, 3, e);
	printf("  (11)输出单链表h:");
	DispList(h);
	printf("  (12)释放单链表h\n");
	DestroyList(h);
	return 1;
}

自己跟着敲一遍确实能理解一些了。

二:将单链表按基准划分。

#include<stdio.h>
#include<string.h>
#include<malloc.h>
typedef char ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;		//指向后继结点
} LinkNode;		 			//单链表结点类型
void CreateListR(LinkNode*& L, ElemType a[], int n)//尾插法建立单链表
{
	LinkNode* s, * r;
	L = (LinkNode*)malloc(sizeof(LinkNode));  	//创建头结点
	L->next = NULL;
	r = L;						//r始终指向尾结点,开始时指向头结点
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
		s->data = a[i];
		r->next = s;				//将结点s插入r结点之后
		r = s;
	}
	r->next = NULL;				//尾结点next域置为NULL
}
void DispList(LinkNode* L)	//输出线性表
{
	LinkNode* p = L->next;	//p指向首结点
	while (p != NULL)			//p不为NULL,输出p结点的data域
	{
		printf("%c ", p->data);
		p = p->next;			//p移向下一个结点
	}
	printf("\n");
}
void DestroyList(LinkNode*& L)	//销毁线性表
{
	LinkNode* pre = L, * p = pre->next;
	while (p != NULL)
	{
		free(pre);
		pre = p;					//pre、p同步后移一个结点					
		p = pre->next;
	}
	free(pre);					//此时p为NULL,pre指向尾结点,释放它
}
void Split1(LinkNode*& L)			//解法1:将L中所有结点按首结点值进行划分
{
	LinkNode* pre, * p, * q;
	if (L->next == NULL || L->next->next == NULL)
		return;						//单链表L为空或者只有一个结点时返回 
	int x = L->next->data;			//取首结点值x 
	pre = L->next;					//pre指向首结点
	p = pre->next;					//p指向pre结点的后继结点 
	while (p != NULL)
	{
		if (p->data < x)				//结点p的值小于x时 
		{
			pre->next = p->next;		//删除结点p
			p->next = L->next;		//将结点p插入到表头
			L->next = p;
			p = pre->next;			//继续遍历 
		}
		else						//结点p的值大于等于x时 
		{
			pre = p;					//pre,p同步后移 
			p = pre->next;
		}
	}
}
void Split2(LinkNode*& L)			//解法2:将L中所有结点按首结点值进行划分
{
	LinkNode* p = L->next, * r, * L1, * r1;
	if (L->next == NULL || L->next->next == NULL)
		return;						//单链表L为空或者只有一个结点时返回 
	int x = L->next->data;			//取首结点值x 
	r = L;
	L1 = (LinkNode*)malloc(sizeof(LinkNode));	//建立大于等于x的单链表L1
	r1 = L1;
	while (p != NULL)
	{
		if (p->data < x)			//若p结点值小于x
		{
			r->next = p; r = p;
			p = p->next;
		}
		else
		{
			r1->next = p; r1 = p;
			p = p->next;
		}
	}
	r1->next = NULL;
	r->next = L1->next;			//L和L1连接 
	free(L1);
}

int main()
{
	LinkNode* L;
	ElemType a[] = "daxgdchaeb";
	int n = strlen(a);
	printf("解法1\n");
	CreateListR(L, a, n);
	printf("  L: "); DispList(L);
	printf("  以首结点值进行划分\n");
	Split1(L);
	printf("  L: "); DispList(L);
	DestroyList(L);
	printf("解法2\n");
	CreateListR(L, a, n);
	printf("  L: "); DispList(L);
	printf("  以首结点值进行划分\n");
	Split2(L);
	printf("  L: "); DispList(L);
	DestroyList(L);
	return 1;
}

看不懂捏

三:将两个单链表合并为一个单链表。

//单链表运算算法
#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;		//指向后继结点
} LinkNode;		 			//单链表结点类型
void CreateListR(LinkNode*& L, ElemType a[], int n)
//尾插法建立单链表
{
	LinkNode* s, * r;
	L = (LinkNode*)malloc(sizeof(LinkNode));  	//创建头结点
	L->next = NULL;
	r = L;						//r始终指向尾结点,开始时指向头结点
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
		s->data = a[i];
		r->next = s;				//将结点s插入r结点之后
		r = s;
	}
	r->next = NULL;				//尾结点next域置为NULL
}
void Merge(LinkNode* L1, LinkNode* L2, LinkNode*& L3) //L1和L2合并产生L3
{
	LinkNode* p = L1->next, * q = L2->next, * r;
	L3 = L1;
	r = L3;				//r指向新建单链表L3的尾结点
	free(L2);			//释放L2的头结点
	while (p != NULL && q != NULL)
	{
		r->next = p; r = p; p = p->next;
		r->next = q; r = q; q = q->next;
	}
	r->next = NULL;
	if (q != NULL) p = q;
	r->next = p;
}
void DispList(LinkNode* L)	//输出线性表
{
	LinkNode* p = L->next;	//p指向首结点
	while (p != NULL)			//p不为NULL,输出p结点的data域
	{
		printf("%c ", p->data);
		p = p->next;			//p移向下一个结点
	}
	printf("\n");
}
void DestroyList(LinkNode*& L)	//销毁线性表
{
	LinkNode* pre = L, * p = pre->next;
	while (p != NULL)
	{
		free(pre);
		pre = p;					//pre、p同步后移一个结点					
		p = pre->next;
	}
	free(pre);					//此时p为NULL,pre指向尾结点,释放它
}
int main()
{
	LinkNode* L1, * L2, * L3;
	ElemType a[] = "abcdefgh";
	int n = 8;
	CreateListR(L1, a, n);
	printf("L1:"); DispList(L1);

	ElemType b[] = "12345";
	n = 5;
	CreateListR(L2, b, n);
	printf("L2:"); DispList(L2);
	printf("L1和L2合并产生L3\n");
	Merge(L1, L2, L3);
	printf("L3:"); DispList(L3);
	DestroyList(L3);
	return 1;
}

四:删除单链表给定的节点运算。

有一带头结点的单链表L,假设元素类型是int,单链表表现有9个元素,分别是3,8,2,7,1,5,2,4,6.设计一个尽可能高效的算法,完成以下功能(可以参考,但不调用linklist.cpp文件)

(1)建立单链表L,在控制台显示单链表表L的所有元素

(2)查找单链表,删除结点值为2的结点,在控制台显示输出删除后的所有结点

#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;		//指向后继结点
} LinkNode;		 			//单链表结点类型
void CreateListR(LinkNode*& L, ElemType a[], int n)  //尾插法建立单链表
{
	LinkNode* s, * r;
	L = (LinkNode*)malloc(sizeof(LinkNode));  	//创建头结点
	L->next = NULL;
	r = L;						//r始终指向尾结点,开始时指向头结点
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
		s->data = a[i];
		r->next = s;				//将结点s插入r结点之后
		r = s;
	}
	r->next = NULL;				//尾结点next域置为NULL
}
void InitList(LinkNode*& L)		//初始化线性表
{
	L = (LinkNode*)malloc(sizeof(LinkNode));  //创建头结点
	L->next = NULL;				//单链表置为空表
}
void DispList(LinkNode* L)	//输出线性表
{
	LinkNode* p = L->next;	//p指向首结点
	while (p != NULL)			//p不为NULL,输出p结点的data域
	{
		printf("%d ", p->data);
		p = p->next;			//p移向下一个结点
	}
	printf("\n");
}
bool ListDelete(LinkNode*& L, int i, ElemType& e)	//删除第i个元素
{
	int j = 0;
	if (i <= 0) return false;		//i错误返回假
	LinkNode* p = L, * q;			//p指向头结点,j置为0(即头结点的序号为0)
	while (j < i - 1 && p != NULL)	//查找第i-1个结点
	{
		j++;
		p = p->next;
	}
	if (p == NULL)				//未找到第i-1个结点,返回false
		return false;
	else						//找到第i-1个结点p
	{
		q = p->next;				//q指向第i个结点
		if (q == NULL)			//若不存在第i个结点,返回false
			return false;
		e = q->data;
		p->next = q->next;		//从单链表中删除q结点
		free(q);				//释放q结点
		return true;			//返回true表示成功删除第i个结点
	}
}
int main()
{
	int a[9] = { 3,8,2,7,1,5,2,4,6 };
	int x;
	LinkNode* L;
	InitList(L);
	CreateListR(L,a,9);
	printf("(1)单链表所有元素为:");
	DispList(L);
	printf("(2)删除值为2的结点后,所有元素:");
	ListDelete(L,3,x);
	ListDelete(L, 6, x);
	DispList(L);
	return 0;
}

五:LeetCode80—删除排序数组中的重复项II。

int removeDuplicates(int* nums, int numsSize) {
    if (numsSize <= 2) {
        return numsSize;
    }
    int slow = 2, fast = 2;
    while (fast < numsSize) {
        if (nums[slow - 2] != nums[fast]) {
            nums[slow] = nums[fast];
            ++slow;
        }
        ++fast;
    }
    return slow;
}

六:LeetCode24—两两交换链表中的结点。

struct ListNode* swapPairs(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    struct ListNode* newHead = head->next;
    head->next = swapPairs(newHead->next);
    newHead->next = head;
    return newHead;
}

代码来自力扣官方

七:删除单链表元素最大的节点运算。

有一带头结点的单链表L,假设元素类型是int,单链表表现有10个元素,分别是31,46,82,17,61,35,22,14,46,25.设计一个尽可能高效的算法,先建立该单链表,在控制台输出显示结点排列。然后删除该单链表中最大的元素结点,并在控制台输出显示删除后的结点排列(可以参考,但不调用linklist.cpp文件)

#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;		//指向后继结点
} LinkNode;		 			//单链表结点类型
void CreateListR(LinkNode*& L, ElemType a[], int n)  //尾插法建立单链表
{
	LinkNode* s, * r;
	L = (LinkNode*)malloc(sizeof(LinkNode));  	//创建头结点
	L->next = NULL;
	r = L;						//r始终指向尾结点,开始时指向头结点
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
		s->data = a[i];
		r->next = s;				//将结点s插入r结点之后
		r = s;
	}
	r->next = NULL;				//尾结点next域置为NULL
}
void InitList(LinkNode*& L)		//初始化线性表
{
	L = (LinkNode*)malloc(sizeof(LinkNode));  //创建头结点
	L->next = NULL;				//单链表置为空表
}
void DispList(LinkNode* L)	//输出线性表
{
	LinkNode* p = L->next;	//p指向首结点
	while (p != NULL)			//p不为NULL,输出p结点的data域
	{
		printf("%d ", p->data);
		p = p->next;			//p移向下一个结点
	}
	printf("\n");
}
bool ListDelete(LinkNode*& L, int i, ElemType& e)	//删除第i个元素
{
	int j = 0;
	if (i <= 0) return false;		//i错误返回假
	LinkNode* p = L, * q;			//p指向头结点,j置为0(即头结点的序号为0)
	while (j < i - 1 && p != NULL)	//查找第i-1个结点
	{
		j++;
		p = p->next;
	}
	if (p == NULL)				//未找到第i-1个结点,返回false
		return false;
	else						//找到第i-1个结点p
	{
		q = p->next;				//q指向第i个结点
		if (q == NULL)			//若不存在第i个结点,返回false
			return false;
		e = q->data;
		p->next = q->next;		//从单链表中删除q结点
		free(q);				//释放q结点
		return true;			//返回true表示成功删除第i个结点
	}
}
void delmaxnode(LinkNode*& L)
{
	LinkNode* p = L->next, * pre = L, * maxp = p, * maxpre = pre;
	while (p != NULL)
	{
		if (maxp->data < p->data)
		{
			maxp = p;
			maxpre = pre;
		}
		pre = p;
		p = p->next;
	}
	maxpre->next = maxp->next;
	free(maxp);
}
int main()
{
	int a[10] = {31,46,82,17,61,35,22,14,46,25};

	int x;
	LinkNode* L;
	InitList(L);
	CreateListR(L,a,9);
	printf("(1)单链表所有元素为:");
	DispList(L);
	printf("(2)删除值最大的元素结点后的所有元素:");
	delmaxnode(L);
	DispList(L);
	return 0;
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇