1、单链表的创建和遍历
2、求单链表中节点的个数(太简单,就不写了)
3、查找单链表中的倒数第k个结点(剑指offer,题15)
4、查找单链表中的中间结点
5、合并两个有序的单链表,合并之后的链表依然有序【出现频率高】(剑指offer,题17)
6、单链表的反转【出现频率最高】(剑指offer,题16)
7、从尾到头打印单链表(剑指offer,题5)
8、判断单链表是否有环
9、取出有环链表中,环的长度
10、单链表中,取出环的起始点(剑指offer,题56)。本题需利用上面的第8题和第9题。
11、判断两个单链表相交的第一个交点(剑指offer,题37)
完整代码(一)
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
/* 1,创建链表,初始化,遍历 3,找到倒数第k个节点。 4,找到中间节点。 6,逆置要求空间复杂度o(1),时间复杂度o(n) */
/*
创建链表:创建链表增删
*/
/**
链表节点
*/
typedef struct knode{
ElemType data;
struct knode *next;
// struct knode *prior;
}linknode;
// 创建头结点
linknode *create(){
linknode *root;
root = (linknode *)malloc(sizeof(linknode));
root->next = NULL;
// root->prior = NULL;
return root;
}
// 从头部开始添加节点
void insert(linknode *s,int i) {
linknode *p;
while(i != 0) {
p = (linknode *)malloc(sizeof(linknode));
p->next = s->next;
// p->prior = s;
s->next =p;
// printf("输入插入的数据:");
scanf("%c",&p->data); // 前面不能有其他输入流
i--;
}
}
// 遍历节点,并且返回节点长度。
int ergodic(linknode *s){
int length = 0;
s = s->next;
if(s == NULL) return length;
while(s){
printf("%c ",s->data);
s = s->next;
length++;
}
return length;
}
// 长度
int length(linknode *s){
int len = 0;
s = s->next;
if(s == NULL) return len;
while(s){
s = s->next;
len++;
}
return len;
}
// 2.1)单链表,找到倒数第k个节点。并且输出。
int find(linknode *s,int k){
int len,t;
len = length(s);
s = s->next;
if(s == NULL) return 0;
if(len < k) return 0;
t = len - k;
while(t-1 != 0){
s = s->next;
t--;
}
s = s->next;
printf("第k个元素是%c\n",s->data);
return 1;
}
/*
2.2)链表找到倒数第k个节点。
*/
int finds(linknode *s,int k){
linknode *q,*p;
q=p=s;
if(s == NULL) return 0;
while(q != NULL && (k-1) != 0){ // q 到顺数第k个节点。
q = q->next;
k--;
return 0;
}
while(q->next != NULL && p != NULL){ // q->next如果为空,就表示结束向前移动。
q = q->next;
p = p->next;
}
printf("中间的节点:%c\n",p->data);
return 1;
}
// 输出链表中间节点。
void middle(linknode *s){
int len,t;
len = length(s);
if(len % 2 == 1){
t = len/2 +1;
}else{
t = len/2;
}
while(t != 0){
s = s->next;
t--;
}
printf("这是中间的节点%c\n",s->data);
}
// 链表逆置,空间O(1)
/*
*/
linknode *reverse(linknode *s){
linknode *head,*p,*r,*d;
d = r = head = s;
s = head->next; // s 指向第一个节点。
while(s != NULL) {
p = s->next; // 让p指向s的下一个节点。
s->next = head; // s 节点逆指向。
head = s; // head 节点向前移动。
s = p; // s节点向前移动,最后结果 s = NULL, p = NULL
}
d = r->next; // d 就是为了找到最后一个节点。让它的next = NULL。r->next和最后一个节点在此时是双向的。
d->next = NULL; // 尾节点next为NULL
r->next = head;
return r;
}
// 合并两个有序链表,非递归方法。
void main(){
linknode *s,*r;
s = create();
// 插入
int i,length;
printf("插入节点的个数:");
scanf("%d",&i);
insert(s,i);
//遍历
length = ergodic(s);
printf("链表的长度%d\n",length);
find(s,3);
//输出中间节点
middle(s);
//查倒数第k个节点
finds(s,3);
//逆置
r = reverse(s);
ergodic(r);
printf("\n");
}
完整代码(二)
/** 5, 链表的合并。 7,(在不改变链表结构的前提下)逆序输出单链表的值 */
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
typedef char ElemType;
typedef struct node{
ElemType data;
struct node *next;
}linknode;
// 创建链表
linknode *create(){
linknode *root;
root = (linknode *)malloc(sizeof(linknode));
root->next = NULL;
root->data = NULL;
return root;
}
// 初始化链表
void init(linknode *s,int k){
linknode *p;
cout<<"输入有序的字符串:";
for(int i = 0; i < k; i++){
p = create();
cin>>p->data;
s->next = p;
s = p;
}
}
// 遍历,带头结点的。
void pt(linknode *s){
cout<<"输出内容:";
s = s->next;
while(s){
cout<<s->data;
s = s->next;
}
cout<<endl;
}
// 遍历不带头结点的。
void pts(linknode *s){
cout<<"输出内容:";
while(s){
cout<<s->data;
s = s->next;
}
cout<<endl;
}
//merge 合并有序链表(有序)(带头结点的)
linknode *merge(linknode *s,linknode *r){
linknode *p,*p1,*p2,*root;
// 两个链表都非空
if(s->next == NULL) {
return r;
}
if(r->next == NULL) {
return s;
}
p1 = s->next;
p2 = r->next;
// 确定那个链表,成为新的链表头
if(p1->data <= p2->data){
root = p1;
p = p1; // p指向新选出的节点。
p1 = p1->next;
}else{
root = p2;
p = p2;
p2 = p2->next;
}
//合并
while(p1 != NULL && p2 != NULL) {
if(p1->data <= p2->data) {
p->next = p1;
p1 = p1->next;
}else{
p->next = p2;
p2 = p2->next;
}
p = p->next;
}
//如果有一个链表为空
if(p1){
p->next = p1;
}
if(p2){
p->next = p2;
}
return root;
}
// (在不改变链表结构的前提下)逆序输出单链表的值
void outputs(linknode *s){
if(s != NULL){ // 递归基
if(s->next != NULL){
outputs(s->next);
}
}
cout<<s->data; // 平凡事务
}
void main(){
linknode *s,*r,*h;
int k;
// 创建连接并且输出。
cout<<"输入链表长度:";
cin>>k;
s = create();
init(s,k);
// 创建链表并且输出
cout<<"输入链表长度:";
cin>>k;
r = create();
init(r,k);
//输出
pt(s);
pt(r);
//合并
h = merge(s,r);
pts(h);
// 逆输出h
cout<<"非结构改变逆输出:";
outputs(h);
cout<<endl;
}