Skip to content Skip to footer

C/C++链表的基本操作(新建,输出,删除,插入,查找,逆序,排序,释放链表,链表长度计算,查找倒数第k节点的元素)

链表的一些操作(新建,输出,删除,插入,查找,逆序,排序,释放链表,链表长度计算,查找倒数第k节点的元素)

一. 链表的概念

1、链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,有一系列结点(地址)组成,结点可动态的生成。

2、结点包括两个部分:

一、存储数据元素的数据域(内存空间)

二、存储指向下一个结点地址的指针域。

3、相对于线性表顺序结构,操作复杂。

二.链表的作用

1、实现数据元素的存储按一定顺序储存,允许在任意位置插入和删除结点。

2、包括单向结点,双向结点,循环接点

3、C/C++/Java都可以实现

三.链表的优缺点

优点:链表实现数据元素储存的顺序储存,是连续的

缺点:因为含有大量的指针域,所以占用空间大,同时因为只有头结点(后面说明)是明确知道地址的,所以查找链表中的元素需要从头开始寻找,非常麻烦。

四.建立一个链表结点结构

struct linked_list

{

int num;

linked_list *next;

};

五.对链表的操作

介于本人初学链表,只能对单链表进行一些基础操作

1.新建链表(新建一个长度为n的链表)

linked_list* create(linked_list *head,int n)

{

linked_list *ptr,*tail=NULL;

head=NULL;

for(int i=0;i

{

ptr=(linked_list*)malloc(sizeof(linked_list));

scanf("%d",&ptr->num);

ptr->next=NULL;

if(!head)

head=ptr;//对首节点进行赋值

else

tail->next=ptr;//新增链表尾部

tail=ptr;//尾节点移动

}

return head;

}//新建一个长度为n的链表并返回首节点的地址

2.删除(释放)链表

在单链表中我们在程序的最后加上一个释放内存的方法或者操作,这是一个很好的习惯。(我对这个操作其实不是很懂,有问题请指出,以下是我对代码)

void release(linked_list *head)

{

linked_list *ptr=head;

while(head)

{

ptr=head;

head=head->next;

free(ptr);

}

free(head);

if(!head)

cout<<"链表已删除,请重新输入链表长度\n";

}//删除整个链表

3.插入一个数据到链表中的某个位置

linked_list* insert(linked_list* head, linked_list* ptr, int n, int l)

{

linked_list* h = head;

if (n == 1)//插入到第一个位置

{

ptr->next = head;

head = ptr;

}

else

{

for (int i = 0;i < n - 2;i++)

h = h->next;

ptr->next = h->next;

h->next = ptr;

}

return head;

}//插入某个数据到n位置 ,并返回首节点

4.删除链表中的第n个位置的的节点

我用的方法是覆盖法

当需要删除一个节点p时,只需要将p的前一个节点的next赋为p->next,但是由于是单向的,只知道p,无法知道p前一个节点,所以需要转换思路。将p下一个的节点覆盖到p节点即可,这样就等效于将p删除了。(当然呢我这并没有把那个节点给释放掉,不知道会不会出问题)

linked_list* del(linked_list* head, int l, int n)

{

linked_list* h = head;

if (l == 1)//删除首节点

head = head->next;

else//删除中间节点

{

for (int i = 0;i < l - 2;i++)

h = h->next;

h->next = h->next->next;

}

return head;

}//删除第l个位置的节点,并返回首节点

5.对单向链表第a到第b位置的节点反转

思路是这样的:

要求将一带链表头List head的单向链表逆序。

分析:

1). 若链表为空或只有一个元素,则直接返回;

2). 设置两个前后相邻的指针p,q. 将p所指向的节点作为q指向节点的后继;

3). 重复2),直到q为空

4). 调整链表头和链表尾

Alt

linked_list* reverse(linked_list *head,int a,int b,int n)

{

linked_list *p=head,*q=head->next,*s=NULL,*h=head;

if(a>b)

{

int temp=a;

a=b;

b=temp;

}

int qq=b-a,t=a-2;

if(head==NULL||head->next==NULL||a==b)//当链表为空或者链表只有一个节点或者a==b时候,直接返回head

return head;

if(a==1&&b>1)//a==1时候对链表a到b进行逆序

{

b--;

while(b--)

{

s=q->next;

q->next=p;

p=q;

q=s;

}

head->next=q;

head=p;

return head;

}

//a!=1的时候对a到b位置进行逆序

a--;

while(a--)

{

p=p->next;

q=q->next;

}//p移动到第a个位置,q移动到a+1个位置

while(t--)

h=h->next;//h是p的前一个位置

while(qq--)//对第a个位置到第b个位置的链表进行倒序

{

s=q->next;

q->next=p;

p=q;

q=s;

}

h->next->next=q;

h->next=p;

return head;

}//对链表a到b位置的数据逆序并返回head的位置;

6.查找链表中数据为a的第一个节点的位置

int find(linked_list *head,int a,int n)

{

int sum=1;

while(head)

{

if(head->num==a)

break;

sum++;

head=head->next;

}

if(sum>n)

return -1;

return sum;

}//查找数据为a的节点的位置

7.链表排序操作

linked_list* linked_listsort(linked_list *head,int p)//p判断进行升序还是降序操作

{

linked_list *slow=head,*fast=NULL;

int temp;

if(p==1)//升序排序

{

while(slow)//冒泡思想,就不解释了

{

fast=slow->next;

while(fast)

{

if(fast->numnum)

{

temp=slow->num;

slow->num=fast->num;

fast->num=temp;

}

fast=fast->next;

}

slow=slow->next;

}

cout<<"你已进行了升序排序,查看排序结果请输入1\n";

}

else//降序排序

{

while(slow)

{

fast=slow->next;

while(fast)

{

if(fast->num>slow->num)

{

temp=slow->num;

slow->num=fast->num;

fast->num=temp;

}

fast=fast->next;

}

slow=slow->next;

}

cout<<"你已进行了降序排序,查看排序结果请输入1\n";

}

return head;

}

8.计算链表长度

int lengthofLinklist(linked_list *head)

{

int len = 0;

while(head)

{

head=head->next;

len++;

}

return len;

}//计算链表长度

9.查找链表倒数第k个元素

//两次遍历查找倒数第k元素

linked_list* findKthTail(linked_list *head, int k)

{

if (head==NULL || k<=0) return NULL;

int len = 0;

linked_list *root=head;

while (head)

{

head=head->next;

len++;

}

if (len

int countdown = len-k;

while (countdown--)

root=root->next;

return root;

}

//快慢指针 查找倒数第k元素

linked_list* findKthTail2(linked_list* head, int k)

{

if (head == NULL || k <= 0) return NULL;

linked_list *slow = head;

linked_list *fast = head;

for(int i=0;i

{ //快指针先走k步

if(fast)

fast = fast->next;

else

return NULL;//如果k>链表长度 返回NULL;

}

while(fast) //相当于slow移动了 链表长度len - k步;

{

fast = fast->next;

slow = slow->next;

}

return slow;

}

10.代码整合

#include

using namespace std;

struct linked_list

{

int num;

linked_list* next;

};

linked_list* reverse(linked_list* head, int a, int b, int n)

{

linked_list* p = head, * q = head->next, * s = NULL, * h = head;

if (a > b)

{

int temp = a;

a = b;

b = temp;

}

int qq = b - a, t = a - 2;

if (head == NULL || head->next == NULL || a == b)//当链表为空或者链表只有一个节点或者a==b时候,直接返回head

return head;

if (a == 1 && b > 1)//a==1时候对链表a到b进行逆序

{

b--;

while (b--)

{

s = q->next;

q->next = p;

p = q;

q = s;

}

head->next = q;

head = p;

return head;

}

//a!=1的时候对a到b位置进行逆序

a--;

while (a--)

{

p = p->next;

q = q->next;

}//p移动到第a个位置,q移动到a+1个位置

while (t--)

h = h->next;//h是p的前一个位置

while (qq--)//对第a个位置到第b个位置的链表进行倒序

{

s = q->next;

q->next = p;

p = q;

q = s;

}

h->next->next = q;

h->next = p;

return head;

}//对链表a到b位置的数据逆序并返回head的位置;

//head是首节点,l是待删除位置,n是链表长度

//这个函数的l和n和上个插入函数的不大一样,无伤大雅吧,嘿嘿

linked_list* del(linked_list* head, int l, int n)

{

linked_list* h = head;

if (l == 1)//删除首节点

head = head->next;

else//删除中间节点

{

for (int i = 0;i < l - 2;i++)

h = h->next;

h->next = h->next->next;

}

return head;

}//删除第l个位置的节点,并返回首节点

//head是首节点,ptr是存放待插入数据的节点,l是链表长度,n是待插入的位置

linked_list* insert(linked_list* head, linked_list* ptr, int n, int l)

{

linked_list* h = head;

if (n == 1)//插入到第一个位置

{

ptr->next = head;

head = ptr;

}

else

{

for (int i = 0;i < n - 2;i++)

h = h->next;

ptr->next = h->next;

h->next = ptr;

}

return head;

}//插入某个数据到n位置 ,并返回首节点

void release(linked_list* head)

{

linked_list* ptr = head;

while (head)

{

ptr = head;

head = head->next;

free(ptr);

}

free(head);

if (!head)

cout << "链表已删除,请重新输入链表长度\n";

}//删除整个链表

linked_list* create(linked_list* head, int n)

{

linked_list* ptr, * tail = NULL;

head = NULL;

for (int i = 0;i < n;i++)

{

ptr = (linked_list*)malloc(sizeof(linked_list));

cin >> ptr->num;

ptr->next = NULL;

if (!head)

head = ptr;//对首节点进行赋值

else

tail->next = ptr;//新增链表尾部

tail = ptr;//尾节点移动

}

return head;

}//新建一个长度为n的链表并返回首节点的地址

int find(linked_list* head, int a, int n)

{

int sum = 1;

while (head)

{

if (head->num == a)

break;

sum++;

head = head->next;

}

if (sum > n)

return -1;

return sum;

}//查找数据为a的节点的位置

int lengthofLinklist(linked_list* head)

{

int len = 0;

while (head)

{

head = head->next;

len++;

}

return len;

}//计算链表长度

linked_list* linked_listsort(linked_list* head, int p)//p判断进行升序还是降序操作

{

linked_list* slow = head, * fast = NULL;

int temp;

if (p == 1)//升序排序

{

while (slow)//冒泡思想,就不解释了

{

fast = slow->next;

while (fast)

{

if (fast->num < slow->num)

{

temp = slow->num;

slow->num = fast->num;

fast->num = temp;

}

fast = fast->next;

}

slow = slow->next;

}

cout << "你已进行了升序排序,查看排序结果请输入1\n";

}

else//降序排序

{

while (slow)

{

fast = slow->next;

while (fast)

{

if (fast->num > slow->num)

{

temp = slow->num;

slow->num = fast->num;

fast->num = temp;

}

fast = fast->next;

}

slow = slow->next;

}

cout << "你已进行了降序排序,查看排序结果请输入1\n";

}

return head;

}

//两次遍历查找倒数第k元素

linked_list* findKthTail(linked_list* head, int k)

{

if (head == NULL || k <= 0) return NULL;

int len = 0;

linked_list* root = head;

while (head)

{

head = head->next;

len++;

}

if (len < k) return NULL;

int countdown = len - k;

while (countdown--)

root = root->next;

return root;

}

//快慢指针 查找倒数第k元素

linked_list* findKthTail2(linked_list* head, int k)

{

if (head == NULL || k <= 0) return NULL;

linked_list* slow = head;

linked_list* fast = head;

for (int i = 0;i < k;i++)

{ //快指针先走k步

if (fast)

fast = fast->next;

else

return NULL;//如果k>链表长度 返回NULL;

}

while (fast) //相当于slow移动了 链表长度len - k步;

{

fast = fast->next;

slow = slow->next;

}

return slow;

}

int main()

{

int n, q, op, a, b, p, k;

cout << "请输入链表长度\n";

while (cin >> n)

{

linked_list* head;

head = (linked_list*)malloc(sizeof(linked_list));

cout << "请输入" << n << "个数据存入链表\n";

head = create(head, n);

cout << "请输入你要进行的操作:\n";

cout << "1.输出链表\n";

cout << "2.删除链表第q个位置的数据\n";

cout << "3.输入一个数据插入到第q个位置\n";

cout << "4.对链表a到b位置的数据进行逆序\n";

cout << "5.查找某个元素所在节点的位置\n";

cout << "6.对链表进行排序\n";

cout << "7.查找链表导数第k个元素\n";

cout << "8.删除并释放链表\n";

while (1)

{

linked_list* h = head;

cin >> op;

if (op == 1)

{

h = head;

cout << "长度为" << lengthofLinklist(h) << "的链表为:\n";

while (h)

{

cout << h->num << " ";

h = h->next;

}

cout << endl << endl << "你还要进行什么操作?" << endl;

}

else if (op == 2)

{

cout << "请输入你要删除的位置:";

cin >> q;

head = del(head, q, n);

cout << "你已删除第" << q << "位置的数据,要看输出结果请输入1\n";

n--;//链表长度-1

}

else if (op == 3)

{

linked_list* ptr = NULL;

ptr = (linked_list*)malloc(sizeof(linked_list));

cout << "请输入待插入的数据:";

cin >> ptr->num;

ptr->next = NULL;

cout << "你要将" << ptr->num << "这个数据插入哪个位置?\n" << "请输入待插入的位置:";

cin >> q;

head = insert(head, ptr, q, n);

cout << "要看输出结果请输入1\n";

n++;//链表长度+1;

}

else if (op == 4)

{

cout << "请输入a和b,对链表第a位置和第b位置的链表反转\n";

cin >> a >> b;

head = reverse(head, a, b, n);

cout << "已对链表第" << a << "到第" << b << "位置的数据进行了反转\n";

cout << "要看输出结果请输入1\n";

}

else if (op == 5)

{

cout << "请输入你要查找的元素:";

cin >> a;

int node = find(head, a, n);

if (node < 0)

cout << "链表中没有这个元素\n";

else

cout << a << "在第" << node << "个位置\n";

cout << endl << "你还要进行什么操作?" << endl;

}

else if (op == 6)

{

cout << "你要进行升序(1)排序还是降序(2)排序?请输入你选择的排序方法:";

cin >> p;

head = linked_listsort(head, p);

}

else if (op == 7)

{

cout << "请输入你想查找链表中倒数第几个节点位置的值:";

cin >> k;

if (k > lengthofLinklist(head))

{

cout << "输入的长度不合法,此时链表长度为:" << lengthofLinklist(head);

cout << "请重新输入7 进行此操作\n";

}

else

{

linked_list* q = findKthTail(head, k);

cout << "链表中倒数第" << k << "个位置节点的值为:" << q->num << endl << "你还要进行什么操作?" << endl;

}

}

else if (op == 8)

{

release(head);

break;

}

else

cout << "输入的操作不对哦!\n请重新输入\n";

}

}

return 0;

}

在借鉴了好多大牛写的博客之后,写出了我第一篇博客;

希望有任何问题大家可以指出,我会改进的!!!

Copyright © 2088 乒乓球世界杯几年一次_世界杯冠军 - salooo.com All Rights Reserved.
友情链接